src/share/vm/classfile/symbolTable.cpp

changeset 5743
63147986a428
parent 5277
01522ca68fc7
child 5775
461159cd7a91
child 5784
190899198332
     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.

mercurial