< prev index next >

src/share/vm/classfile/stringTable.cpp

Print this page
rev 12679 : 8176593: Throwable::getStackTrace performance regression
Reviewed-by: jiangli, iklam, coleenp, sspitsyn
   1 /*
   2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


  79     int check_size = sample(check_buf);
  80     return (0 == memcmp(_save_buf, check_buf, check_size));
  81   }
  82 
  83   void set_region(const void* region) { _region = (address) region; }
  84 };
  85 #endif
  86 
  87 
  88 // --------------------------------------------------------------------------
  89 StringTable* StringTable::_the_table = NULL;
  90 bool StringTable::_ignore_shared_strings = false;
  91 bool StringTable::_needs_rehashing = false;
  92 
  93 volatile int StringTable::_parallel_claimed_idx = 0;
  94 
  95 CompactHashtable<oop, char> StringTable::_shared_table;
  96 
  97 // Pick hashing algorithm
  98 unsigned int StringTable::hash_string(const jchar* s, int len) {
  99   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
 100                                     java_lang_String::hash_code(s, len);
 101 }
 102 




 103 unsigned int StringTable::hash_string(oop string) {
 104   EXCEPTION_MARK;
 105   if (string == NULL) {
 106     return hash_string((jchar*)NULL, 0);
 107   }
 108   ResourceMark rm(THREAD);
 109   // All String oops are hashed as unicode
 110   int length;
 111   jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD);
 112   if (chars != NULL) {
 113     return hash_string(chars, length);
 114   } else {
 115     vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
 116     return 0;
 117   }
 118 }
 119 
 120 oop StringTable::lookup_shared(jchar* name, int len) {
 121   // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't
 122   // use the hash value from StringTable::hash_string() as it might use alternate hashcode.
 123   return _shared_table.lookup((const char*)name,
 124                               java_lang_String::hash_code(name, len), len);
 125 }
 126 
 127 oop StringTable::lookup_in_main_table(int index, jchar* name,
 128                                 int len, unsigned int hash) {
 129   int count = 0;
 130   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
 131     count++;
 132     if (l->hash() == hash) {
 133       if (java_lang_String::equals(l->literal(), name, len)) {
 134         return l->literal();
 135       }
 136     }
 137   }
 138   // If the bucket size is too deep check if this hash code is insufficient.
 139   if (count >= rehash_count && !needs_rehashing()) {
 140     _needs_rehashing = check_rehash_table(count);
 141   }
 142   return NULL;
 143 }
 144 
 145 
 146 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
 147                            int len, unsigned int hashValue_arg, TRAPS) {
 148 
 149   assert(java_lang_String::equals(string(), name, len),
 150          "string must be properly initialized");
 151   // Cannot hit a safepoint in this function because the "this" pointer can move.
 152   NoSafepointVerifier nsv;
 153 
 154   // Check if the symbol table has been rehashed, if so, need to recalculate
 155   // the hash value and index before second lookup.
 156   unsigned int hashValue;
 157   int index;
 158   if (use_alternate_hashcode()) {
 159     hashValue = hash_string(name, len);
 160     index = hash_to_index(hashValue);
 161   } else {
 162     hashValue = hashValue_arg;
 163     index = index_arg;
 164   }
 165 
 166   // Since look-up was done lock-free, we need to check if another
 167   // thread beat us in the race to insert the symbol.
 168 
 169   // No need to lookup the shared table from here since the caller (intern()) already did
 170   oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
 171   if (test != NULL) {
 172     // Entry already added
 173     return test;
 174   }
 175 
 176   HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
 177   add_entry(index, entry);
 178   return string();
 179 }


 182 oop StringTable::lookup(Symbol* symbol) {
 183   ResourceMark rm;
 184   int length;
 185   jchar* chars = symbol->as_unicode(length);
 186   return lookup(chars, length);
 187 }
 188 
 189 // Tell the GC that this string was looked up in the StringTable.
 190 static void ensure_string_alive(oop string) {
 191   // A lookup in the StringTable could return an object that was previously
 192   // considered dead. The SATB part of G1 needs to get notified about this
 193   // potential resurrection, otherwise the marking might not find the object.
 194 #if INCLUDE_ALL_GCS
 195   if (UseG1GC && string != NULL) {
 196     G1SATBCardTableModRefBS::enqueue(string);
 197   }
 198 #endif
 199 }
 200 
 201 oop StringTable::lookup(jchar* name, int len) {
 202   oop string = lookup_shared(name, len);


 203   if (string != NULL) {
 204     return string;
 205   }
 206 
 207   unsigned int hash = hash_string(name, len);

 208   int index = the_table()->hash_to_index(hash);
 209   string = the_table()->lookup_in_main_table(index, name, len, hash);
 210 
 211   ensure_string_alive(string);
 212 
 213   return string;
 214 }
 215 
 216 oop StringTable::intern(Handle string_or_null, jchar* name,
 217                         int len, TRAPS) {
 218   oop found_string = lookup_shared(name, len);


 219   if (found_string != NULL) {
 220     return found_string;
 221   }
 222 
 223   unsigned int hashValue = hash_string(name, len);

 224   int index = the_table()->hash_to_index(hashValue);
 225   found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
 226 
 227   // Found
 228   if (found_string != NULL) {
 229     if (found_string != string_or_null()) {
 230       ensure_string_alive(found_string);
 231     }
 232     return found_string;
 233   }
 234 
 235   debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
 236   assert(!Universe::heap()->is_in_reserved(name),
 237          "proposed name of symbol must be stable");
 238 
 239   Handle string;
 240   // try to reuse the string if possible
 241   if (!string_or_null.is_null()) {
 242     string = string_or_null;
 243   } else {


   1 /*
   2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


  79     int check_size = sample(check_buf);
  80     return (0 == memcmp(_save_buf, check_buf, check_size));
  81   }
  82 
  83   void set_region(const void* region) { _region = (address) region; }
  84 };
  85 #endif
  86 
  87 
  88 // --------------------------------------------------------------------------
  89 StringTable* StringTable::_the_table = NULL;
  90 bool StringTable::_ignore_shared_strings = false;
  91 bool StringTable::_needs_rehashing = false;
  92 
  93 volatile int StringTable::_parallel_claimed_idx = 0;
  94 
  95 CompactHashtable<oop, char> StringTable::_shared_table;
  96 
  97 // Pick hashing algorithm
  98 unsigned int StringTable::hash_string(const jchar* s, int len) {
  99   return use_alternate_hashcode() ? alt_hash_string(s, len) :
 100                                     java_lang_String::hash_code(s, len);
 101 }
 102 
 103 unsigned int StringTable::alt_hash_string(const jchar* s, int len) {
 104   return AltHashing::murmur3_32(seed(), s, len);
 105 }
 106 
 107 unsigned int StringTable::hash_string(oop string) {
 108   EXCEPTION_MARK;
 109   if (string == NULL) {
 110     return hash_string((jchar*)NULL, 0);
 111   }
 112   ResourceMark rm(THREAD);
 113   // All String oops are hashed as unicode
 114   int length;
 115   jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD);
 116   if (chars != NULL) {
 117     return hash_string(chars, length);
 118   } else {
 119     vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
 120     return 0;
 121   }
 122 }
 123 
 124 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
 125   assert(hash == java_lang_String::hash_code(name, len),
 126          "hash must be computed using java_lang_String::hash_code");
 127   return _shared_table.lookup((const char*)name, hash, len);

 128 }
 129 
 130 oop StringTable::lookup_in_main_table(int index, jchar* name,
 131                                 int len, unsigned int hash) {
 132   int count = 0;
 133   for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
 134     count++;
 135     if (l->hash() == hash) {
 136       if (java_lang_String::equals(l->literal(), name, len)) {
 137         return l->literal();
 138       }
 139     }
 140   }
 141   // If the bucket size is too deep check if this hash code is insufficient.
 142   if (count >= rehash_count && !needs_rehashing()) {
 143     _needs_rehashing = check_rehash_table(count);
 144   }
 145   return NULL;
 146 }
 147 
 148 
 149 oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
 150                            int len, unsigned int hashValue_arg, TRAPS) {
 151 
 152   assert(java_lang_String::equals(string(), name, len),
 153          "string must be properly initialized");
 154   // Cannot hit a safepoint in this function because the "this" pointer can move.
 155   NoSafepointVerifier nsv;
 156 
 157   // Check if the symbol table has been rehashed, if so, need to recalculate
 158   // the hash value and index before second lookup.
 159   unsigned int hashValue;
 160   int index;
 161   if (use_alternate_hashcode()) {
 162     hashValue = alt_hash_string(name, len);
 163     index = hash_to_index(hashValue);
 164   } else {
 165     hashValue = hashValue_arg;
 166     index = index_arg;
 167   }
 168 
 169   // Since look-up was done lock-free, we need to check if another
 170   // thread beat us in the race to insert the symbol.
 171 
 172   // No need to lookup the shared table from here since the caller (intern()) already did
 173   oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int)
 174   if (test != NULL) {
 175     // Entry already added
 176     return test;
 177   }
 178 
 179   HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
 180   add_entry(index, entry);
 181   return string();
 182 }


 185 oop StringTable::lookup(Symbol* symbol) {
 186   ResourceMark rm;
 187   int length;
 188   jchar* chars = symbol->as_unicode(length);
 189   return lookup(chars, length);
 190 }
 191 
 192 // Tell the GC that this string was looked up in the StringTable.
 193 static void ensure_string_alive(oop string) {
 194   // A lookup in the StringTable could return an object that was previously
 195   // considered dead. The SATB part of G1 needs to get notified about this
 196   // potential resurrection, otherwise the marking might not find the object.
 197 #if INCLUDE_ALL_GCS
 198   if (UseG1GC && string != NULL) {
 199     G1SATBCardTableModRefBS::enqueue(string);
 200   }
 201 #endif
 202 }
 203 
 204 oop StringTable::lookup(jchar* name, int len) {
 205   // shared table always uses java_lang_String::hash_code
 206   unsigned int hash = java_lang_String::hash_code(name, len);
 207   oop string = lookup_shared(name, len, hash);
 208   if (string != NULL) {
 209     return string;
 210   }
 211   if (use_alternate_hashcode()) {
 212     hash = alt_hash_string(name, len);
 213   }
 214   int index = the_table()->hash_to_index(hash);
 215   string = the_table()->lookup_in_main_table(index, name, len, hash);
 216 
 217   ensure_string_alive(string);
 218 
 219   return string;
 220 }
 221 
 222 oop StringTable::intern(Handle string_or_null, jchar* name,
 223                         int len, TRAPS) {
 224   // shared table always uses java_lang_String::hash_code
 225   unsigned int hashValue = java_lang_String::hash_code(name, len);
 226   oop found_string = lookup_shared(name, len, hashValue);
 227   if (found_string != NULL) {
 228     return found_string;
 229   }
 230   if (use_alternate_hashcode()) {
 231     hashValue = alt_hash_string(name, len);
 232   }
 233   int index = the_table()->hash_to_index(hashValue);
 234   found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
 235 
 236   // Found
 237   if (found_string != NULL) {
 238     if (found_string != string_or_null()) {
 239       ensure_string_alive(found_string);
 240     }
 241     return found_string;
 242   }
 243 
 244   debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
 245   assert(!Universe::heap()->is_in_reserved(name),
 246          "proposed name of symbol must be stable");
 247 
 248   Handle string;
 249   // try to reuse the string if possible
 250   if (!string_or_null.is_null()) {
 251     string = string_or_null;
 252   } else {


< prev index next >