src/share/vm/classfile/symbolTable.cpp

Print this page
rev 4551 : 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. Changes were also reviewed by Per Liden <per.liden@oracle.com>.
Reviewed-by: tschatzl, stefank, twisti


 593     _size   = size;
 594     sample(_save_buf);
 595   }
 596 
 597   bool verify() {
 598     u1 check_buf[sizeof(_save_buf)];
 599     int check_size = sample(check_buf);
 600     return (0 == memcmp(_save_buf, check_buf, check_size));
 601   }
 602 
 603   void set_region(const void* region) { _region = (address) region; }
 604 };
 605 #endif
 606 
 607 
 608 // --------------------------------------------------------------------------
 609 StringTable* StringTable::_the_table = NULL;
 610 
 611 bool StringTable::_needs_rehashing = false;
 612 


 613 // Pick hashing algorithm
 614 unsigned int StringTable::hash_string(const jchar* s, int len) {
 615   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
 616                                     java_lang_String::to_hash(s, len);
 617 }
 618 
 619 oop StringTable::lookup(int index, jchar* name,
 620                         int len, unsigned int hash) {
 621   int count = 0;
 622   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
 623     count++;
 624     if (l->hash() == hash) {
 625       if (java_lang_String::equals(l->literal(), name, len)) {
 626         return l->literal();
 627       }
 628     }
 629   }
 630   // If the bucket size is too deep check if this hash code is insufficient.
 631   if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
 632     _needs_rehashing = check_rehash_table(count);


 754     while (entry != NULL) {
 755       // Shared entries are normally at the end of the bucket and if we run into
 756       // a shared entry, then there is nothing more to remove. However, if we
 757       // have rehashed the table, then the shared entries are no longer at the
 758       // end of the bucket.
 759       if (entry->is_shared() && !use_alternate_hashcode()) {
 760         break;
 761       }
 762       assert(entry->literal() != NULL, "just checking");
 763       if (entry->is_shared() || is_alive->do_object_b(entry->literal())) {
 764         p = entry->next_addr();
 765       } else {
 766         *p = entry->next();
 767         the_table()->free_entry(entry);
 768       }
 769       entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
 770     }
 771   }
 772 }
 773 
 774 void StringTable::oops_do(OopClosure* f) {
 775   for (int i = 0; i < the_table()->table_size(); ++i) {










 776     HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
 777     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 778     while (entry != NULL) {
 779       f->do_oop((oop*)entry->literal_addr());
 780 
 781       // Did the closure remove the literal from the table?
 782       if (entry->literal() == NULL) {
 783         assert(!entry->is_shared(), "immutable hashtable entry?");
 784         *p = entry->next();
 785         the_table()->free_entry(entry);
 786       } else {
 787         p = entry->next_addr();
 788       }
 789       entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
 790     }
 791   }
 792 }
 793 





















 794 void StringTable::verify() {
 795   for (int i = 0; i < the_table()->table_size(); ++i) {
 796     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 797     for ( ; p != NULL; p = p->next()) {
 798       oop s = p->literal();
 799       guarantee(s != NULL, "interned string is NULL");
 800       guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace");
 801       unsigned int h = java_lang_String::hash_string(s);
 802       guarantee(p->hash() == h, "broken hash in string table entry");
 803       guarantee(the_table()->hash_to_index(h) == i,
 804                 "wrong index in string table");
 805     }
 806   }
 807 }
 808 
 809 void StringTable::dump(outputStream* st) {
 810   NumberSeq summary;
 811   for (int i = 0; i < the_table()->table_size(); ++i) {
 812     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 813     int count = 0;




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


 756     while (entry != NULL) {
 757       // Shared entries are normally at the end of the bucket and if we run into
 758       // a shared entry, then there is nothing more to remove. However, if we
 759       // have rehashed the table, then the shared entries are no longer at the
 760       // end of the bucket.
 761       if (entry->is_shared() && !use_alternate_hashcode()) {
 762         break;
 763       }
 764       assert(entry->literal() != NULL, "just checking");
 765       if (entry->is_shared() || is_alive->do_object_b(entry->literal())) {
 766         p = entry->next_addr();
 767       } else {
 768         *p = entry->next();
 769         the_table()->free_entry(entry);
 770       }
 771       entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
 772     }
 773   }
 774 }
 775 
 776 void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
 777   const int limit = the_table()->table_size();
 778 
 779   assert(0 <= start_idx && start_idx <= limit,
 780          err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx));
 781   assert(0 <= end_idx && end_idx <= limit,
 782          err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx));
 783   assert(start_idx <= end_idx,
 784          err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
 785                  start_idx, end_idx));
 786 
 787   for (int i = start_idx; i < end_idx; i += 1) {
 788     HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
 789     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
 790     while (entry != NULL) {
 791       f->do_oop((oop*)entry->literal_addr());
 792 
 793       // Did the closure remove the literal from the table?
 794       if (entry->literal() == NULL) {
 795         assert(!entry->is_shared(), "immutable hashtable entry?");
 796         *p = entry->next();
 797         the_table()->free_entry(entry);
 798       } else {
 799         p = entry->next_addr();
 800       }
 801       entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
 802     }
 803   }
 804 }
 805 
 806 void StringTable::oops_do(OopClosure* f) {
 807   buckets_do(f, 0, the_table()->table_size());
 808 }
 809 
 810 void StringTable::possibly_parallel_oops_do(OopClosure* f) {
 811   const int ClaimChunkSize = 32;
 812   const int limit = the_table()->table_size();
 813 
 814   for (;;) {
 815     // Grab next set of buckets to scan
 816     int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
 817     if (start_idx >= limit) {
 818       // End of table
 819       break;
 820     }
 821 
 822     int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
 823     buckets_do(f, start_idx, end_idx);
 824   }
 825 }
 826 
 827 void StringTable::verify() {
 828   for (int i = 0; i < the_table()->table_size(); ++i) {
 829     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 830     for ( ; p != NULL; p = p->next()) {
 831       oop s = p->literal();
 832       guarantee(s != NULL, "interned string is NULL");
 833       guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace");
 834       unsigned int h = java_lang_String::hash_string(s);
 835       guarantee(p->hash() == h, "broken hash in string table entry");
 836       guarantee(the_table()->hash_to_index(h) == i,
 837                 "wrong index in string table");
 838     }
 839   }
 840 }
 841 
 842 void StringTable::dump(outputStream* st) {
 843   NumberSeq summary;
 844   for (int i = 0; i < the_table()->table_size(); ++i) {
 845     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
 846     int count = 0;