src/share/vm/classfile/dictionary.cpp

changeset 5862
82af7d7a0128
parent 5307
e0c9a1d29eb4
child 5865
aa6f2ea19d8f
     1.1 --- a/src/share/vm/classfile/dictionary.cpp	Wed Oct 09 11:18:53 2013 -0700
     1.2 +++ b/src/share/vm/classfile/dictionary.cpp	Wed Oct 09 10:57:01 2013 +0200
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -25,6 +25,7 @@
    1.11  #include "precompiled.hpp"
    1.12  #include "classfile/dictionary.hpp"
    1.13  #include "classfile/systemDictionary.hpp"
    1.14 +#include "memory/iterator.hpp"
    1.15  #include "oops/oop.inline.hpp"
    1.16  #include "prims/jvmtiRedefineClassesTrace.hpp"
    1.17  #include "utilities/hashtable.inline.hpp"
    1.18 @@ -38,17 +39,21 @@
    1.19    : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
    1.20    _current_class_index = 0;
    1.21    _current_class_entry = NULL;
    1.22 +  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
    1.23  };
    1.24  
    1.25  
    1.26 -
    1.27  Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
    1.28                         int number_of_entries)
    1.29    : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
    1.30    _current_class_index = 0;
    1.31    _current_class_entry = NULL;
    1.32 +  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
    1.33  };
    1.34  
    1.35 +ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
    1.36 +  return _pd_cache_table->get(protection_domain);
    1.37 +}
    1.38  
    1.39  DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
    1.40                                         ClassLoaderData* loader_data) {
    1.41 @@ -105,11 +110,12 @@
    1.42  }
    1.43  
    1.44  
    1.45 -void DictionaryEntry::add_protection_domain(oop protection_domain) {
    1.46 +void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
    1.47    assert_locked_or_safepoint(SystemDictionary_lock);
    1.48    if (!contains_protection_domain(protection_domain)) {
    1.49 +    ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
    1.50      ProtectionDomainEntry* new_head =
    1.51 -                new ProtectionDomainEntry(protection_domain, _pd_set);
    1.52 +                new ProtectionDomainEntry(entry, _pd_set);
    1.53      // Warning: Preserve store ordering.  The SystemDictionary is read
    1.54      //          without locks.  The new ProtectionDomainEntry must be
    1.55      //          complete before other threads can be allowed to see it
    1.56 @@ -193,7 +199,10 @@
    1.57  
    1.58  
    1.59  void Dictionary::always_strong_oops_do(OopClosure* blk) {
    1.60 -  // Follow all system classes and temporary placeholders in dictionary
    1.61 +  // Follow all system classes and temporary placeholders in dictionary; only
    1.62 +  // protection domain oops contain references into the heap. In a first
    1.63 +  // pass over the system dictionary determine which need to be treated as
    1.64 +  // strongly reachable and mark them as such.
    1.65    for (int index = 0; index < table_size(); index++) {
    1.66      for (DictionaryEntry *probe = bucket(index);
    1.67                            probe != NULL;
    1.68 @@ -201,10 +210,13 @@
    1.69        Klass* e = probe->klass();
    1.70        ClassLoaderData* loader_data = probe->loader_data();
    1.71        if (is_strongly_reachable(loader_data, e)) {
    1.72 -        probe->protection_domain_set_oops_do(blk);
    1.73 +        probe->set_strongly_reachable();
    1.74        }
    1.75      }
    1.76    }
    1.77 +  // Then iterate over the protection domain cache to apply the closure on the
    1.78 +  // previously marked ones.
    1.79 +  _pd_cache_table->always_strong_oops_do(blk);
    1.80  }
    1.81  
    1.82  
    1.83 @@ -266,18 +278,12 @@
    1.84    }
    1.85  }
    1.86  
    1.87 -
    1.88  void Dictionary::oops_do(OopClosure* f) {
    1.89 -  for (int index = 0; index < table_size(); index++) {
    1.90 -    for (DictionaryEntry* probe = bucket(index);
    1.91 -                          probe != NULL;
    1.92 -                          probe = probe->next()) {
    1.93 -      probe->protection_domain_set_oops_do(f);
    1.94 -    }
    1.95 -  }
    1.96 +  // Only the protection domain oops contain references into the heap. Iterate
    1.97 +  // over all of them.
    1.98 +  _pd_cache_table->oops_do(f);
    1.99  }
   1.100  
   1.101 -
   1.102  void Dictionary::methods_do(void f(Method*)) {
   1.103    for (int index = 0; index < table_size(); index++) {
   1.104      for (DictionaryEntry* probe = bucket(index);
   1.105 @@ -292,6 +298,11 @@
   1.106    }
   1.107  }
   1.108  
   1.109 +void Dictionary::unlink(BoolObjectClosure* is_alive) {
   1.110 +  // Only the protection domain cache table may contain references to the heap
   1.111 +  // that need to be unlinked.
   1.112 +  _pd_cache_table->unlink(is_alive);
   1.113 +}
   1.114  
   1.115  Klass* Dictionary::try_get_next_class() {
   1.116    while (true) {
   1.117 @@ -306,7 +317,6 @@
   1.118    // never reached
   1.119  }
   1.120  
   1.121 -
   1.122  // Add a loaded class to the system dictionary.
   1.123  // Readers of the SystemDictionary aren't always locked, so _buckets
   1.124  // is volatile. The store of the next field in the constructor is
   1.125 @@ -396,7 +406,7 @@
   1.126    assert(protection_domain() != NULL,
   1.127           "real protection domain should be present");
   1.128  
   1.129 -  entry->add_protection_domain(protection_domain());
   1.130 +  entry->add_protection_domain(this, protection_domain());
   1.131  
   1.132    assert(entry->contains_protection_domain(protection_domain()),
   1.133           "now protection domain should be present");
   1.134 @@ -446,6 +456,146 @@
   1.135    }
   1.136  }
   1.137  
   1.138 +ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
   1.139 +  : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
   1.140 +{
   1.141 +}
   1.142 +
   1.143 +void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
   1.144 +  assert(SafepointSynchronize::is_at_safepoint(), "must be");
   1.145 +  for (int i = 0; i < table_size(); ++i) {
   1.146 +    ProtectionDomainCacheEntry** p = bucket_addr(i);
   1.147 +    ProtectionDomainCacheEntry* entry = bucket(i);
   1.148 +    while (entry != NULL) {
   1.149 +      if (is_alive->do_object_b(entry->literal())) {
   1.150 +        p = entry->next_addr();
   1.151 +      } else {
   1.152 +        *p = entry->next();
   1.153 +        free_entry(entry);
   1.154 +      }
   1.155 +      entry = *p;
   1.156 +    }
   1.157 +  }
   1.158 +}
   1.159 +
   1.160 +void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
   1.161 +  for (int index = 0; index < table_size(); index++) {
   1.162 +    for (ProtectionDomainCacheEntry* probe = bucket(index);
   1.163 +                                     probe != NULL;
   1.164 +                                     probe = probe->next()) {
   1.165 +      probe->oops_do(f);
   1.166 +    }
   1.167 +  }
   1.168 +}
   1.169 +
   1.170 +uint ProtectionDomainCacheTable::bucket_size() {
   1.171 +  return sizeof(ProtectionDomainCacheEntry);
   1.172 +}
   1.173 +
   1.174 +#ifndef PRODUCT
   1.175 +void ProtectionDomainCacheTable::print() {
   1.176 +  tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
   1.177 +                table_size(), number_of_entries());
   1.178 +  for (int index = 0; index < table_size(); index++) {
   1.179 +    for (ProtectionDomainCacheEntry* probe = bucket(index);
   1.180 +                                     probe != NULL;
   1.181 +                                     probe = probe->next()) {
   1.182 +      probe->print();
   1.183 +    }
   1.184 +  }
   1.185 +}
   1.186 +
   1.187 +void ProtectionDomainCacheEntry::print() {
   1.188 +  tty->print_cr("entry "PTR_FORMAT" value "PTR_FORMAT" strongly_reachable %d next "PTR_FORMAT,
   1.189 +                this, literal(), _strongly_reachable, next());
   1.190 +}
   1.191 +#endif
   1.192 +
   1.193 +void ProtectionDomainCacheTable::verify() {
   1.194 +  int element_count = 0;
   1.195 +  for (int index = 0; index < table_size(); index++) {
   1.196 +    for (ProtectionDomainCacheEntry* probe = bucket(index);
   1.197 +                                     probe != NULL;
   1.198 +                                     probe = probe->next()) {
   1.199 +      probe->verify();
   1.200 +      element_count++;
   1.201 +    }
   1.202 +  }
   1.203 +  guarantee(number_of_entries() == element_count,
   1.204 +            "Verify of protection domain cache table failed");
   1.205 +  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
   1.206 +}
   1.207 +
   1.208 +void ProtectionDomainCacheEntry::verify() {
   1.209 +  guarantee(literal()->is_oop(), "must be an oop");
   1.210 +}
   1.211 +
   1.212 +void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
   1.213 +  // the caller marked the protection domain cache entries that we need to apply
   1.214 +  // the closure on. Only process them.
   1.215 +  for (int index = 0; index < table_size(); index++) {
   1.216 +    for (ProtectionDomainCacheEntry* probe = bucket(index);
   1.217 +                                     probe != NULL;
   1.218 +                                     probe = probe->next()) {
   1.219 +      if (probe->is_strongly_reachable()) {
   1.220 +        probe->reset_strongly_reachable();
   1.221 +        probe->oops_do(f);
   1.222 +      }
   1.223 +    }
   1.224 +  }
   1.225 +}
   1.226 +
   1.227 +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
   1.228 +  unsigned int hash = compute_hash(protection_domain);
   1.229 +  int index = hash_to_index(hash);
   1.230 +
   1.231 +  ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain);
   1.232 +  if (entry == NULL) {
   1.233 +    entry = add_entry(index, hash, protection_domain);
   1.234 +  }
   1.235 +  return entry;
   1.236 +}
   1.237 +
   1.238 +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
   1.239 +  for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
   1.240 +    if (e->protection_domain() == protection_domain) {
   1.241 +      return e;
   1.242 +    }
   1.243 +  }
   1.244 +
   1.245 +  return NULL;
   1.246 +}
   1.247 +
   1.248 +ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
   1.249 +  assert_locked_or_safepoint(SystemDictionary_lock);
   1.250 +  assert(index == index_for(protection_domain), "incorrect index?");
   1.251 +  assert(find_entry(index, protection_domain) == NULL, "no double entry");
   1.252 +
   1.253 +  ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
   1.254 +  Hashtable<oop, mtClass>::add_entry(index, p);
   1.255 +  return p;
   1.256 +}
   1.257 +
   1.258 +void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
   1.259 +  unsigned int hash = compute_hash(to_delete->protection_domain());
   1.260 +  int index = hash_to_index(hash);
   1.261 +
   1.262 +  ProtectionDomainCacheEntry** p = bucket_addr(index);
   1.263 +  ProtectionDomainCacheEntry* entry = bucket(index);
   1.264 +  while (true) {
   1.265 +    assert(entry != NULL, "sanity");
   1.266 +
   1.267 +    if (entry == to_delete) {
   1.268 +      *p = entry->next();
   1.269 +      Hashtable<oop, mtClass>::free_entry(entry);
   1.270 +      break;
   1.271 +    } else {
   1.272 +      p = entry->next_addr();
   1.273 +      entry = *p;
   1.274 +    }
   1.275 +  }
   1.276 +}
   1.277 +
   1.278  SymbolPropertyTable::SymbolPropertyTable(int table_size)
   1.279    : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
   1.280  {
   1.281 @@ -532,11 +682,13 @@
   1.282        tty->cr();
   1.283      }
   1.284    }
   1.285 +  tty->cr();
   1.286 +  _pd_cache_table->print();
   1.287 +  tty->cr();
   1.288  }
   1.289  
   1.290  #endif
   1.291  
   1.292 -
   1.293  void Dictionary::verify() {
   1.294    guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
   1.295  
   1.296 @@ -563,5 +715,7 @@
   1.297    guarantee(number_of_entries() == element_count,
   1.298              "Verify of system dictionary failed");
   1.299    debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
   1.300 +
   1.301 +  _pd_cache_table->verify();
   1.302  }
   1.303  

mercurial