src/share/vm/classfile/symbolTable.cpp

Print this page
rev 4769 : 8015237: Parallelize string table scanning during strong root processing
Summary: Parallelize the scanning of the intern string table by having each GC worker claim a given number of buckets.
Reviewed-by:


 581     _size   = size;
 582     sample(_save_buf);
 583   }
 584 
 585   bool verify() {
 586     u1 check_buf[sizeof(_save_buf)];
 587     int check_size = sample(check_buf);
 588     return (0 == memcmp(_save_buf, check_buf, check_size));
 589   }
 590 
 591   void set_region(const void* region) { _region = (address) region; }
 592 };
 593 #endif
 594 
 595 
 596 // --------------------------------------------------------------------------
 597 StringTable* StringTable::_the_table = NULL;
 598 
 599 bool StringTable::_needs_rehashing = false;
 600 


 601 // Pick hashing algorithm
 602 unsigned int StringTable::hash_string(const jchar* s, int len) {
 603   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
 604                                     java_lang_String::hash_code(s, len);
 605 }
 606 
 607 oop StringTable::lookup(int index, jchar* name,
 608                         int len, unsigned int hash) {
 609   int count = 0;
 610   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
 611     count++;
 612     if (l->hash() == hash) {
 613       if (java_lang_String::equals(l->literal(), name, len)) {
 614         return l->literal();
 615       }
 616     }
 617   }
 618   // If the bucket size is too deep check if this hash code is insufficient.
 619   if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
 620     _needs_rehashing = check_rehash_table(count);


 744   for (int i = 0; i < the_table()->table_size(); ++i) {
 745     HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
 746     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 747     while (entry != NULL) {
 748       assert(!entry->is_shared(), "CDS not used for the StringTable");
 749 
 750       if (is_alive->do_object_b(entry->literal())) {
 751         if (f != NULL) {
 752           f->do_oop((oop*)entry->literal_addr());
 753         }
 754         p = entry->next_addr();
 755       } else {
 756         *p = entry->next();
 757         the_table()->free_entry(entry);
 758       }
 759       entry = *p;
 760     }
 761   }
 762 }
 763 
 764 void StringTable::oops_do(OopClosure* f) {
 765   for (int i = 0; i < the_table()->table_size(); ++i) {










 766     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 767     while (entry != NULL) {
 768       assert(!entry->is_shared(), "CDS not used for the StringTable");
 769 
 770       f->do_oop((oop*)entry->literal_addr());
 771 
 772       entry = entry->next();
 773     }
 774   }
 775 }
 776 





















 777 void StringTable::verify() {
 778   for (int i = 0; i < the_table()->table_size(); ++i) {
 779     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 780     for ( ; p != NULL; p = p->next()) {
 781       oop s = p->literal();
 782       guarantee(s != NULL, "interned string is NULL");
 783       unsigned int h = java_lang_String::hash_string(s);
 784       guarantee(p->hash() == h, "broken hash in string table entry");
 785       guarantee(the_table()->hash_to_index(h) == i,
 786                 "wrong index in string table");
 787     }
 788   }
 789 }
 790 
 791 void StringTable::dump(outputStream* st) {
 792   the_table()->dump_table(st, "StringTable");
 793 }
 794 
 795 
 796 // Create a new table and using alternate hash code, populate the new table


 581     _size   = size;
 582     sample(_save_buf);
 583   }
 584 
 585   bool verify() {
 586     u1 check_buf[sizeof(_save_buf)];
 587     int check_size = sample(check_buf);
 588     return (0 == memcmp(_save_buf, check_buf, check_size));
 589   }
 590 
 591   void set_region(const void* region) { _region = (address) region; }
 592 };
 593 #endif
 594 
 595 
 596 // --------------------------------------------------------------------------
 597 StringTable* StringTable::_the_table = NULL;
 598 
 599 bool StringTable::_needs_rehashing = false;
 600 
 601 volatile int StringTable::_par_claimed_idx = 0;
 602 
 603 // Pick hashing algorithm
 604 unsigned int StringTable::hash_string(const jchar* s, int len) {
 605   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
 606                                     java_lang_String::hash_code(s, len);
 607 }
 608 
 609 oop StringTable::lookup(int index, jchar* name,
 610                         int len, unsigned int hash) {
 611   int count = 0;
 612   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
 613     count++;
 614     if (l->hash() == hash) {
 615       if (java_lang_String::equals(l->literal(), name, len)) {
 616         return l->literal();
 617       }
 618     }
 619   }
 620   // If the bucket size is too deep check if this hash code is insufficient.
 621   if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
 622     _needs_rehashing = check_rehash_table(count);


 746   for (int i = 0; i < the_table()->table_size(); ++i) {
 747     HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
 748     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 749     while (entry != NULL) {
 750       assert(!entry->is_shared(), "CDS not used for the StringTable");
 751 
 752       if (is_alive->do_object_b(entry->literal())) {
 753         if (f != NULL) {
 754           f->do_oop((oop*)entry->literal_addr());
 755         }
 756         p = entry->next_addr();
 757       } else {
 758         *p = entry->next();
 759         the_table()->free_entry(entry);
 760       }
 761       entry = *p;
 762     }
 763   }
 764 }
 765 
 766 void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
 767   const int limit = the_table()->table_size();
 768 
 769   assert(0 <= start_idx && start_idx <= limit,
 770          err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx));
 771   assert(0 <= end_idx && end_idx <= limit,
 772          err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx));
 773   assert(start_idx <= end_idx,
 774          err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
 775                  start_idx, end_idx));
 776 
 777   for (int i = start_idx; i < end_idx; i += 1) {
 778     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 779     while (entry != NULL) {
 780       assert(!entry->is_shared(), "CDS not used for the StringTable");
 781 
 782       f->do_oop((oop*)entry->literal_addr());
 783 
 784       entry = entry->next();
 785     }
 786   }
 787 }
 788 
 789 void StringTable::oops_do(OopClosure* f) {
 790   buckets_do(f, 0, the_table()->table_size());
 791 }
 792 
 793 void StringTable::possibly_parallel_oops_do(OopClosure* f) {
 794   const int ClaimChunkSize = 32;
 795   const int limit = the_table()->table_size();
 796 
 797   for (;;) {
 798     // Grab next set of buckets to scan
 799     int start_idx = Atomic::add(ClaimChunkSize, &_par_claimed_idx) - ClaimChunkSize;
 800     if (start_idx >= limit) {
 801       // End of table
 802       break;
 803     }
 804 
 805     int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
 806     buckets_do(f, start_idx, end_idx);
 807   }
 808 }
 809 
 810 void StringTable::verify() {
 811   for (int i = 0; i < the_table()->table_size(); ++i) {
 812     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 813     for ( ; p != NULL; p = p->next()) {
 814       oop s = p->literal();
 815       guarantee(s != NULL, "interned string is NULL");
 816       unsigned int h = java_lang_String::hash_string(s);
 817       guarantee(p->hash() == h, "broken hash in string table entry");
 818       guarantee(the_table()->hash_to_index(h) == i,
 819                 "wrong index in string table");
 820     }
 821   }
 822 }
 823 
 824 void StringTable::dump(outputStream* st) {
 825   the_table()->dump_table(st, "StringTable");
 826 }
 827 
 828 
 829 // Create a new table and using alternate hash code, populate the new table