comparison src/share/vm/classfile/dictionary.cpp @ 12837:82af7d7a0128

8003420: NPG: make new GC root for pd_set Summary: Move protection domain oops from system dictionary entries into a seperate set; the system dictionary references entries in that set now. This allows fast iteration during non-classunloading garbage collection. Implementation based on initial prototype from Ioi Lam (iklam). Reviewed-by: coleenp, iklam
author tschatzl
date Wed, 09 Oct 2013 10:57:01 +0200
parents e0c9a1d29eb4
children aa6f2ea19d8f
comparison
equal deleted inserted replaced
12836:b4d8a3d4db73 12837:82af7d7a0128
1 /* 1 /*
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
23 */ 23 */
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "classfile/dictionary.hpp" 26 #include "classfile/dictionary.hpp"
27 #include "classfile/systemDictionary.hpp" 27 #include "classfile/systemDictionary.hpp"
28 #include "memory/iterator.hpp"
28 #include "oops/oop.inline.hpp" 29 #include "oops/oop.inline.hpp"
29 #include "prims/jvmtiRedefineClassesTrace.hpp" 30 #include "prims/jvmtiRedefineClassesTrace.hpp"
30 #include "utilities/hashtable.inline.hpp" 31 #include "utilities/hashtable.inline.hpp"
31 32
32 33
36 37
37 Dictionary::Dictionary(int table_size) 38 Dictionary::Dictionary(int table_size)
38 : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) { 39 : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
39 _current_class_index = 0; 40 _current_class_index = 0;
40 _current_class_entry = NULL; 41 _current_class_entry = NULL;
42 _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
41 }; 43 };
42
43 44
44 45
45 Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t, 46 Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
46 int number_of_entries) 47 int number_of_entries)
47 : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) { 48 : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
48 _current_class_index = 0; 49 _current_class_index = 0;
49 _current_class_entry = NULL; 50 _current_class_entry = NULL;
51 _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
50 }; 52 };
51 53
54 ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
55 return _pd_cache_table->get(protection_domain);
56 }
52 57
53 DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass, 58 DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
54 ClassLoaderData* loader_data) { 59 ClassLoaderData* loader_data) {
55 DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass); 60 DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
56 entry->set_loader_data(loader_data); 61 entry->set_loader_data(loader_data);
103 } 108 }
104 return false; 109 return false;
105 } 110 }
106 111
107 112
108 void DictionaryEntry::add_protection_domain(oop protection_domain) { 113 void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
109 assert_locked_or_safepoint(SystemDictionary_lock); 114 assert_locked_or_safepoint(SystemDictionary_lock);
110 if (!contains_protection_domain(protection_domain)) { 115 if (!contains_protection_domain(protection_domain)) {
116 ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
111 ProtectionDomainEntry* new_head = 117 ProtectionDomainEntry* new_head =
112 new ProtectionDomainEntry(protection_domain, _pd_set); 118 new ProtectionDomainEntry(entry, _pd_set);
113 // Warning: Preserve store ordering. The SystemDictionary is read 119 // Warning: Preserve store ordering. The SystemDictionary is read
114 // without locks. The new ProtectionDomainEntry must be 120 // without locks. The new ProtectionDomainEntry must be
115 // complete before other threads can be allowed to see it 121 // complete before other threads can be allowed to see it
116 // via a store to _pd_set. 122 // via a store to _pd_set.
117 OrderAccess::release_store_ptr(&_pd_set, new_head); 123 OrderAccess::release_store_ptr(&_pd_set, new_head);
191 return class_was_unloaded; 197 return class_was_unloaded;
192 } 198 }
193 199
194 200
195 void Dictionary::always_strong_oops_do(OopClosure* blk) { 201 void Dictionary::always_strong_oops_do(OopClosure* blk) {
196 // Follow all system classes and temporary placeholders in dictionary 202 // Follow all system classes and temporary placeholders in dictionary; only
203 // protection domain oops contain references into the heap. In a first
204 // pass over the system dictionary determine which need to be treated as
205 // strongly reachable and mark them as such.
197 for (int index = 0; index < table_size(); index++) { 206 for (int index = 0; index < table_size(); index++) {
198 for (DictionaryEntry *probe = bucket(index); 207 for (DictionaryEntry *probe = bucket(index);
199 probe != NULL; 208 probe != NULL;
200 probe = probe->next()) { 209 probe = probe->next()) {
201 Klass* e = probe->klass(); 210 Klass* e = probe->klass();
202 ClassLoaderData* loader_data = probe->loader_data(); 211 ClassLoaderData* loader_data = probe->loader_data();
203 if (is_strongly_reachable(loader_data, e)) { 212 if (is_strongly_reachable(loader_data, e)) {
204 probe->protection_domain_set_oops_do(blk); 213 probe->set_strongly_reachable();
205 } 214 }
206 } 215 }
207 } 216 }
217 // Then iterate over the protection domain cache to apply the closure on the
218 // previously marked ones.
219 _pd_cache_table->always_strong_oops_do(blk);
208 } 220 }
209 221
210 222
211 void Dictionary::always_strong_classes_do(KlassClosure* closure) { 223 void Dictionary::always_strong_classes_do(KlassClosure* closure) {
212 // Follow all system classes and temporary placeholders in dictionary 224 // Follow all system classes and temporary placeholders in dictionary
264 f(k, probe->loader_data()); 276 f(k, probe->loader_data());
265 } 277 }
266 } 278 }
267 } 279 }
268 280
269
270 void Dictionary::oops_do(OopClosure* f) { 281 void Dictionary::oops_do(OopClosure* f) {
271 for (int index = 0; index < table_size(); index++) { 282 // Only the protection domain oops contain references into the heap. Iterate
272 for (DictionaryEntry* probe = bucket(index); 283 // over all of them.
273 probe != NULL; 284 _pd_cache_table->oops_do(f);
274 probe = probe->next()) { 285 }
275 probe->protection_domain_set_oops_do(f);
276 }
277 }
278 }
279
280 286
281 void Dictionary::methods_do(void f(Method*)) { 287 void Dictionary::methods_do(void f(Method*)) {
282 for (int index = 0; index < table_size(); index++) { 288 for (int index = 0; index < table_size(); index++) {
283 for (DictionaryEntry* probe = bucket(index); 289 for (DictionaryEntry* probe = bucket(index);
284 probe != NULL; 290 probe != NULL;
290 } 296 }
291 } 297 }
292 } 298 }
293 } 299 }
294 300
301 void Dictionary::unlink(BoolObjectClosure* is_alive) {
302 // Only the protection domain cache table may contain references to the heap
303 // that need to be unlinked.
304 _pd_cache_table->unlink(is_alive);
305 }
295 306
296 Klass* Dictionary::try_get_next_class() { 307 Klass* Dictionary::try_get_next_class() {
297 while (true) { 308 while (true) {
298 if (_current_class_entry != NULL) { 309 if (_current_class_entry != NULL) {
299 Klass* k = _current_class_entry->klass(); 310 Klass* k = _current_class_entry->klass();
303 _current_class_index = (_current_class_index + 1) % table_size(); 314 _current_class_index = (_current_class_index + 1) % table_size();
304 _current_class_entry = bucket(_current_class_index); 315 _current_class_entry = bucket(_current_class_index);
305 } 316 }
306 // never reached 317 // never reached
307 } 318 }
308
309 319
310 // Add a loaded class to the system dictionary. 320 // Add a loaded class to the system dictionary.
311 // Readers of the SystemDictionary aren't always locked, so _buckets 321 // Readers of the SystemDictionary aren't always locked, so _buckets
312 // is volatile. The store of the next field in the constructor is 322 // is volatile. The store of the next field in the constructor is
313 // also cast to volatile; we do this to ensure store order is maintained 323 // also cast to volatile; we do this to ensure store order is maintained
394 404
395 assert(entry != NULL,"entry must be present, we just created it"); 405 assert(entry != NULL,"entry must be present, we just created it");
396 assert(protection_domain() != NULL, 406 assert(protection_domain() != NULL,
397 "real protection domain should be present"); 407 "real protection domain should be present");
398 408
399 entry->add_protection_domain(protection_domain()); 409 entry->add_protection_domain(this, protection_domain());
400 410
401 assert(entry->contains_protection_domain(protection_domain()), 411 assert(entry->contains_protection_domain(protection_domain()),
402 "now protection domain should be present"); 412 "now protection domain should be present");
403 } 413 }
404 414
444 p->set_next(bucket(index)); 454 p->set_next(bucket(index));
445 set_entry(index, p); 455 set_entry(index, p);
446 } 456 }
447 } 457 }
448 458
459 ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
460 : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
461 {
462 }
463
464 void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
465 assert(SafepointSynchronize::is_at_safepoint(), "must be");
466 for (int i = 0; i < table_size(); ++i) {
467 ProtectionDomainCacheEntry** p = bucket_addr(i);
468 ProtectionDomainCacheEntry* entry = bucket(i);
469 while (entry != NULL) {
470 if (is_alive->do_object_b(entry->literal())) {
471 p = entry->next_addr();
472 } else {
473 *p = entry->next();
474 free_entry(entry);
475 }
476 entry = *p;
477 }
478 }
479 }
480
481 void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
482 for (int index = 0; index < table_size(); index++) {
483 for (ProtectionDomainCacheEntry* probe = bucket(index);
484 probe != NULL;
485 probe = probe->next()) {
486 probe->oops_do(f);
487 }
488 }
489 }
490
491 uint ProtectionDomainCacheTable::bucket_size() {
492 return sizeof(ProtectionDomainCacheEntry);
493 }
494
495 #ifndef PRODUCT
496 void ProtectionDomainCacheTable::print() {
497 tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
498 table_size(), number_of_entries());
499 for (int index = 0; index < table_size(); index++) {
500 for (ProtectionDomainCacheEntry* probe = bucket(index);
501 probe != NULL;
502 probe = probe->next()) {
503 probe->print();
504 }
505 }
506 }
507
508 void ProtectionDomainCacheEntry::print() {
509 tty->print_cr("entry "PTR_FORMAT" value "PTR_FORMAT" strongly_reachable %d next "PTR_FORMAT,
510 this, literal(), _strongly_reachable, next());
511 }
512 #endif
513
514 void ProtectionDomainCacheTable::verify() {
515 int element_count = 0;
516 for (int index = 0; index < table_size(); index++) {
517 for (ProtectionDomainCacheEntry* probe = bucket(index);
518 probe != NULL;
519 probe = probe->next()) {
520 probe->verify();
521 element_count++;
522 }
523 }
524 guarantee(number_of_entries() == element_count,
525 "Verify of protection domain cache table failed");
526 debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
527 }
528
529 void ProtectionDomainCacheEntry::verify() {
530 guarantee(literal()->is_oop(), "must be an oop");
531 }
532
533 void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
534 // the caller marked the protection domain cache entries that we need to apply
535 // the closure on. Only process them.
536 for (int index = 0; index < table_size(); index++) {
537 for (ProtectionDomainCacheEntry* probe = bucket(index);
538 probe != NULL;
539 probe = probe->next()) {
540 if (probe->is_strongly_reachable()) {
541 probe->reset_strongly_reachable();
542 probe->oops_do(f);
543 }
544 }
545 }
546 }
547
548 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
549 unsigned int hash = compute_hash(protection_domain);
550 int index = hash_to_index(hash);
551
552 ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain);
553 if (entry == NULL) {
554 entry = add_entry(index, hash, protection_domain);
555 }
556 return entry;
557 }
558
559 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
560 for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
561 if (e->protection_domain() == protection_domain) {
562 return e;
563 }
564 }
565
566 return NULL;
567 }
568
569 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
570 assert_locked_or_safepoint(SystemDictionary_lock);
571 assert(index == index_for(protection_domain), "incorrect index?");
572 assert(find_entry(index, protection_domain) == NULL, "no double entry");
573
574 ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
575 Hashtable<oop, mtClass>::add_entry(index, p);
576 return p;
577 }
578
579 void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
580 unsigned int hash = compute_hash(to_delete->protection_domain());
581 int index = hash_to_index(hash);
582
583 ProtectionDomainCacheEntry** p = bucket_addr(index);
584 ProtectionDomainCacheEntry* entry = bucket(index);
585 while (true) {
586 assert(entry != NULL, "sanity");
587
588 if (entry == to_delete) {
589 *p = entry->next();
590 Hashtable<oop, mtClass>::free_entry(entry);
591 break;
592 } else {
593 p = entry->next_addr();
594 entry = *p;
595 }
596 }
597 }
598
449 SymbolPropertyTable::SymbolPropertyTable(int table_size) 599 SymbolPropertyTable::SymbolPropertyTable(int table_size)
450 : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry)) 600 : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
451 { 601 {
452 } 602 }
453 SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t, 603 SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t,
530 tty->print(", loader "); 680 tty->print(", loader ");
531 loader_data->print_value(); 681 loader_data->print_value();
532 tty->cr(); 682 tty->cr();
533 } 683 }
534 } 684 }
685 tty->cr();
686 _pd_cache_table->print();
687 tty->cr();
535 } 688 }
536 689
537 #endif 690 #endif
538
539 691
540 void Dictionary::verify() { 692 void Dictionary::verify() {
541 guarantee(number_of_entries() >= 0, "Verify of system dictionary failed"); 693 guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
542 694
543 int element_count = 0; 695 int element_count = 0;
561 } 713 }
562 } 714 }
563 guarantee(number_of_entries() == element_count, 715 guarantee(number_of_entries() == element_count,
564 "Verify of system dictionary failed"); 716 "Verify of system dictionary failed");
565 debug_only(verify_lookup_length((double)number_of_entries() / table_size())); 717 debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
566 } 718
567 719 _pd_cache_table->verify();
720 }
721