1.1 --- a/src/share/vm/classfile/symbolTable.cpp Tue Sep 17 20:20:03 2013 +0200 1.2 +++ b/src/share/vm/classfile/symbolTable.cpp Wed Sep 18 07:02:10 2013 -0700 1.3 @@ -807,6 +807,8 @@ 1.4 } 1.5 } 1.6 1.7 +// This verification is part of Universe::verify() and needs to be quick. 1.8 +// See StringTable::verify_and_compare() below for exhaustive verification. 1.9 void StringTable::verify() { 1.10 for (int i = 0; i < the_table()->table_size(); ++i) { 1.11 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); 1.12 @@ -825,6 +827,162 @@ 1.13 the_table()->dump_table(st, "StringTable"); 1.14 } 1.15 1.16 +StringTable::VerifyRetTypes StringTable::compare_entries( 1.17 + int bkt1, int e_cnt1, 1.18 + HashtableEntry<oop, mtSymbol>* e_ptr1, 1.19 + int bkt2, int e_cnt2, 1.20 + HashtableEntry<oop, mtSymbol>* e_ptr2) { 1.21 + // These entries are sanity checked by verify_and_compare_entries() 1.22 + // before this function is called. 1.23 + oop str1 = e_ptr1->literal(); 1.24 + oop str2 = e_ptr2->literal(); 1.25 + 1.26 + if (str1 == str2) { 1.27 + tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") " 1.28 + "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]", 1.29 + str1, bkt1, e_cnt1, bkt2, e_cnt2); 1.30 + return _verify_fail_continue; 1.31 + } 1.32 + 1.33 + if (java_lang_String::equals(str1, str2)) { 1.34 + tty->print_cr("ERROR: identical String values in entry @ " 1.35 + "bucket[%d][%d] and entry @ bucket[%d][%d]", 1.36 + bkt1, e_cnt1, bkt2, e_cnt2); 1.37 + return _verify_fail_continue; 1.38 + } 1.39 + 1.40 + return _verify_pass; 1.41 +} 1.42 + 1.43 +StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt, 1.44 + HashtableEntry<oop, mtSymbol>* e_ptr, 1.45 + StringTable::VerifyMesgModes mesg_mode) { 1.46 + 1.47 + VerifyRetTypes ret = _verify_pass; // be optimistic 1.48 + 1.49 + oop str = e_ptr->literal(); 1.50 + if (str == NULL) { 1.51 + if (mesg_mode == _verify_with_mesgs) { 1.52 + tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt, 1.53 + e_cnt); 1.54 + } 1.55 + // NULL oop means no more verifications are possible 1.56 + return _verify_fail_done; 1.57 + } 1.58 + 1.59 + if (str->klass() != SystemDictionary::String_klass()) { 1.60 + if (mesg_mode == _verify_with_mesgs) { 1.61 + tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]", 1.62 + bkt, e_cnt); 1.63 + } 1.64 + // not a String means no more verifications are possible 1.65 + return _verify_fail_done; 1.66 + } 1.67 + 1.68 + unsigned int h = java_lang_String::hash_string(str); 1.69 + if (e_ptr->hash() != h) { 1.70 + if (mesg_mode == _verify_with_mesgs) { 1.71 + tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], " 1.72 + "bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h); 1.73 + } 1.74 + ret = _verify_fail_continue; 1.75 + } 1.76 + 1.77 + if (the_table()->hash_to_index(h) != bkt) { 1.78 + if (mesg_mode == _verify_with_mesgs) { 1.79 + tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], " 1.80 + "str_hash=%d, hash_to_index=%d", bkt, e_cnt, h, 1.81 + the_table()->hash_to_index(h)); 1.82 + } 1.83 + ret = _verify_fail_continue; 1.84 + } 1.85 + 1.86 + return ret; 1.87 +} 1.88 + 1.89 +// See StringTable::verify() above for the quick verification that is 1.90 +// part of Universe::verify(). This verification is exhaustive and 1.91 +// reports on every issue that is found. StringTable::verify() only 1.92 +// reports on the first issue that is found. 1.93 +// 1.94 +// StringTable::verify_entry() checks: 1.95 +// - oop value != NULL (same as verify()) 1.96 +// - oop value is a String 1.97 +// - hash(String) == hash in entry (same as verify()) 1.98 +// - index for hash == index of entry (same as verify()) 1.99 +// 1.100 +// StringTable::compare_entries() checks: 1.101 +// - oops are unique across all entries 1.102 +// - String values are unique across all entries 1.103 +// 1.104 +int StringTable::verify_and_compare_entries() { 1.105 + assert(StringTable_lock->is_locked(), "sanity check"); 1.106 + 1.107 + int fail_cnt = 0; 1.108 + 1.109 + // first, verify all the entries individually: 1.110 + for (int bkt = 0; bkt < the_table()->table_size(); bkt++) { 1.111 + HashtableEntry<oop, mtSymbol>* e_ptr = the_table()->bucket(bkt); 1.112 + for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) { 1.113 + VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs); 1.114 + if (ret != _verify_pass) { 1.115 + fail_cnt++; 1.116 + } 1.117 + } 1.118 + } 1.119 + 1.120 + // Optimization: if the above check did not find any failures, then 1.121 + // the comparison loop below does not need to call verify_entry() 1.122 + // before calling compare_entries(). If there were failures, then we 1.123 + // have to call verify_entry() to see if the entry can be passed to 1.124 + // compare_entries() safely. When we call verify_entry() in the loop 1.125 + // below, we do so quietly to void duplicate messages and we don't 1.126 + // increment fail_cnt because the failures have already been counted. 1.127 + bool need_entry_verify = (fail_cnt != 0); 1.128 + 1.129 + // second, verify all entries relative to each other: 1.130 + for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) { 1.131 + HashtableEntry<oop, mtSymbol>* e_ptr1 = the_table()->bucket(bkt1); 1.132 + for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) { 1.133 + if (need_entry_verify) { 1.134 + VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1, 1.135 + _verify_quietly); 1.136 + if (ret == _verify_fail_done) { 1.137 + // cannot use the current entry to compare against other entries 1.138 + continue; 1.139 + } 1.140 + } 1.141 + 1.142 + for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) { 1.143 + HashtableEntry<oop, mtSymbol>* e_ptr2 = the_table()->bucket(bkt2); 1.144 + int e_cnt2; 1.145 + for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) { 1.146 + if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) { 1.147 + // skip the entries up to and including the one that 1.148 + // we're comparing against 1.149 + continue; 1.150 + } 1.151 + 1.152 + if (need_entry_verify) { 1.153 + VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2, 1.154 + _verify_quietly); 1.155 + if (ret == _verify_fail_done) { 1.156 + // cannot compare against this entry 1.157 + continue; 1.158 + } 1.159 + } 1.160 + 1.161 + // compare two entries, report and count any failures: 1.162 + if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2) 1.163 + != _verify_pass) { 1.164 + fail_cnt++; 1.165 + } 1.166 + } 1.167 + } 1.168 + } 1.169 + } 1.170 + return fail_cnt; 1.171 +} 1.172 1.173 // Create a new table and using alternate hash code, populate the new table 1.174 // with the existing strings. Set flag to use the alternate hash code afterwards.