247 static int literal_size(nmethod*) { return 0; } 248 #endif 249 250 static int literal_size(Symbol *symbol) { 251 return symbol->size() * HeapWordSize; 252 } 253 254 static int literal_size(oop obj) { 255 // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true, 256 // and the String.value array is shared by several Strings. However, starting from JDK8, 257 // the String.value array is not shared anymore. 258 if (obj == NULL) { 259 return 0; 260 } else if (obj->klass() == SystemDictionary::String_klass()) { 261 return (obj->size() + java_lang_String::value(obj)->size()) * HeapWordSize; 262 } else { 263 return obj->size(); 264 } 265 } 266 267 268 // Dump footprint and bucket length statistics 269 // 270 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to 271 // add a new function static int literal_size(MyNewType lit) 272 // because I can't get template <class T> int literal_size(T) to pick the specializations for Symbol and oop. 273 // 274 // The StringTable and SymbolTable dumping print how much footprint is used by the String and Symbol 275 // literals. 276 277 template <class T, MEMFLAGS F> void Hashtable<T, F>::print_table_statistics(outputStream* st, 278 const char *table_name) { 279 NumberSeq summary; 280 int literal_bytes = 0; 281 for (int i = 0; i < this->table_size(); ++i) { 282 int count = 0; 283 for (HashtableEntry<T, F>* e = this->bucket(i); 284 e != NULL; e = e->next()) { 285 count++; 286 literal_bytes += literal_size(e->literal()); | 247 static int literal_size(nmethod*) { return 0; } 248 #endif 249 250 static int literal_size(Symbol *symbol) { 251 return symbol->size() * HeapWordSize; 252 } 253 254 static int literal_size(oop obj) { 255 // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true, 256 // and the String.value array is shared by several Strings. However, starting from JDK8, 257 // the String.value array is not shared anymore. 258 if (obj == NULL) { 259 return 0; 260 } else if (obj->klass() == SystemDictionary::String_klass()) { 261 return (obj->size() + java_lang_String::value(obj)->size()) * HeapWordSize; 262 } else { 263 return obj->size(); 264 } 265 } 266 267 template <MEMFLAGS F> bool BasicHashtable<F>::resize(int new_size) { 268 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 269 270 // Allocate new buckets 271 HashtableBucket<F>* buckets_new = NEW_C_HEAP_ARRAY2_RETURN_NULL(HashtableBucket<F>, new_size, F, CURRENT_PC); 272 if (buckets_new == NULL) { 273 return false; 274 } 275 276 // Clear the new buckets 277 for (int i = 0; i < new_size; i++) { 278 buckets_new[i].clear(); 279 } 280 281 int table_size_old = _table_size; 282 // hash_to_index() uses _table_size, so switch the sizes now 283 _table_size = new_size; 284 285 // Move entries from the old table to a new table 286 for (int index_old = 0; index_old < table_size_old; index_old++) { 287 for (BasicHashtableEntry<F>* p = _buckets[index_old].get_entry(); p != NULL; ) { 288 BasicHashtableEntry<F>* next = p->next(); 289 bool keep_shared = p->is_shared(); 290 int index_new = hash_to_index(p->hash()); 291 292 p->set_next(buckets_new[index_new].get_entry()); 293 buckets_new[index_new].set_entry(p); 294 295 if (keep_shared) { 296 p->set_shared(); 297 } 298 p = next; 299 } 300 } 301 302 // The old backets now can be released 303 BasicHashtable<F>::free_buckets(); 304 305 // Switch to the new storage 306 _buckets = buckets_new; 307 308 return true; 309 } 310 311 // Dump footprint and bucket length statistics 312 // 313 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to 314 // add a new function static int literal_size(MyNewType lit) 315 // because I can't get template <class T> int literal_size(T) to pick the specializations for Symbol and oop. 316 // 317 // The StringTable and SymbolTable dumping print how much footprint is used by the String and Symbol 318 // literals. 319 320 template <class T, MEMFLAGS F> void Hashtable<T, F>::print_table_statistics(outputStream* st, 321 const char *table_name) { 322 NumberSeq summary; 323 int literal_bytes = 0; 324 for (int i = 0; i < this->table_size(); ++i) { 325 int count = 0; 326 for (HashtableEntry<T, F>* e = this->bucket(i); 327 e != NULL; e = e->next()) { 328 count++; 329 literal_bytes += literal_size(e->literal()); |