src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp

changeset 10008
fd3484fadbe3
parent 9327
f96fcd9e1e1b
child 10009
8adf45218add
equal deleted inserted replaced
10007:cb1e375e88a9 10008:fd3484fadbe3
148 void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) { 148 void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) {
149 assert(entry->obj() != NULL, "Double free"); 149 assert(entry->obj() != NULL, "Double free");
150 assert(worker_id < _nlists, "Invalid worker id"); 150 assert(worker_id < _nlists, "Invalid worker id");
151 151
152 entry->set_obj(NULL); 152 entry->set_obj(NULL);
153 entry->set_hash(0); 153 entry->set_java_hash(0);
154 154
155 if (_cached[worker_id].length() < _max_list_length) { 155 if (_cached[worker_id].length() < _max_list_length) {
156 // Cache is not full 156 // Cache is not full
157 _cached[worker_id].add(entry); 157 _cached[worker_id].add(entry);
158 } else { 158 } else {
213 uintx G1StringDedupTable::_entries_added = 0; 213 uintx G1StringDedupTable::_entries_added = 0;
214 uintx G1StringDedupTable::_entries_removed = 0; 214 uintx G1StringDedupTable::_entries_removed = 0;
215 uintx G1StringDedupTable::_resize_count = 0; 215 uintx G1StringDedupTable::_resize_count = 0;
216 uintx G1StringDedupTable::_rehash_count = 0; 216 uintx G1StringDedupTable::_rehash_count = 0;
217 217
218 G1StringDedupTable::G1StringDedupTable(size_t size, jint hash_seed) : 218 G1StringDedupTable::G1StringDedupTable(size_t size, uint64_t hash_seed) :
219 _size(size), 219 _size(size),
220 _entries(0), 220 _entries(0),
221 _grow_threshold((uintx)(size * _grow_load_factor)), 221 _grow_threshold((uintx)(size * _grow_load_factor)),
222 _shrink_threshold((uintx)(size * _shrink_load_factor)), 222 _shrink_threshold((uintx)(size * _shrink_load_factor)),
223 _rehash_needed(false), 223 _rehash_needed(false),
235 assert(_table == NULL, "One string deduplication table allowed"); 235 assert(_table == NULL, "One string deduplication table allowed");
236 _entry_cache = new G1StringDedupEntryCache((size_t)(_min_size * _max_cache_factor)); 236 _entry_cache = new G1StringDedupEntryCache((size_t)(_min_size * _max_cache_factor));
237 _table = new G1StringDedupTable(_min_size); 237 _table = new G1StringDedupTable(_min_size);
238 } 238 }
239 239
240 void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) { 240 void G1StringDedupTable::add(typeArrayOop value, uint64_t hash, G1StringDedupEntry** list) {
241 G1StringDedupEntry* entry = _entry_cache->alloc(); 241 G1StringDedupEntry* entry = _entry_cache->alloc();
242 entry->set_obj(value); 242 entry->set_obj(value);
243 entry->set_hash(hash); 243 if (use_java_hash()) {
244 entry->set_java_hash((unsigned int)hash);
245 } else {
246 entry->set_alt_hash(hash);
247 }
244 entry->set_next(*list); 248 entry->set_next(*list);
245 *list = entry; 249 *list = entry;
246 _entries++; 250 _entries++;
247 } 251 }
248 252
253 } 257 }
254 258
255 void G1StringDedupTable::transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest) { 259 void G1StringDedupTable::transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest) {
256 G1StringDedupEntry* entry = *pentry; 260 G1StringDedupEntry* entry = *pentry;
257 *pentry = entry->next(); 261 *pentry = entry->next();
258 unsigned int hash = entry->hash(); 262 uint64_t hash = use_java_hash() ? entry->java_hash() : entry->alt_hash();
259 size_t index = dest->hash_to_index(hash); 263 size_t index = dest->hash_to_index(hash);
260 G1StringDedupEntry** list = dest->bucket(index); 264 G1StringDedupEntry** list = dest->bucket(index);
261 entry->set_next(*list); 265 entry->set_next(*list);
262 *list = entry; 266 *list = entry;
263 } 267 }
268 (!memcmp(value1->base(T_CHAR), 272 (!memcmp(value1->base(T_CHAR),
269 value2->base(T_CHAR), 273 value2->base(T_CHAR),
270 value1->length() * sizeof(jchar))))); 274 value1->length() * sizeof(jchar)))));
271 } 275 }
272 276
273 typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash, 277 typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, uint64_t hash,
274 G1StringDedupEntry** list, uintx &count) { 278 G1StringDedupEntry** list, uintx &count) {
275 for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) { 279 for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) {
276 if (entry->hash() == hash) { 280 if ((use_java_hash() ? entry->java_hash() : entry->alt_hash()) == hash) {
277 typeArrayOop existing_value = entry->obj(); 281 typeArrayOop existing_value = entry->obj();
278 if (equals(value, existing_value)) { 282 if (equals(value, existing_value)) {
279 // Match found 283 // Match found
280 return existing_value; 284 return existing_value;
281 } 285 }
285 289
286 // Not found 290 // Not found
287 return NULL; 291 return NULL;
288 } 292 }
289 293
290 typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigned int hash) { 294 typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, uint64_t hash) {
291 size_t index = hash_to_index(hash); 295 size_t index = hash_to_index(hash);
292 G1StringDedupEntry** list = bucket(index); 296 G1StringDedupEntry** list = bucket(index);
293 uintx count = 0; 297 uintx count = 0;
294 298
295 // Lookup in list 299 // Lookup in list
309 } 313 }
310 314
311 return existing_value; 315 return existing_value;
312 } 316 }
313 317
314 unsigned int G1StringDedupTable::hash_code(typeArrayOop value) { 318 unsigned int G1StringDedupTable::java_hash_code(typeArrayOop value) {
319 assert(use_java_hash(), "Should not use java hash code");
315 unsigned int hash; 320 unsigned int hash;
316 int length = value->length(); 321 int length = value->length();
317 const jchar* data = (jchar*)value->base(T_CHAR); 322 const jchar* data = (jchar*)value->base(T_CHAR);
318 323
319 if (use_java_hash()) { 324 hash = java_lang_String::hash_code(data, length);
320 hash = java_lang_String::hash_code(data, length);
321 } else {
322 hash = AltHashing::murmur3_32(_table->_hash_seed, data, length);
323 }
324 325
325 return hash; 326 return hash;
327 }
328
329 uint64_t G1StringDedupTable::alt_hash_code(typeArrayOop value) {
330 assert(!use_java_hash(), "Should not use alt hash code");
331
332 int length = value->length();
333 const jbyte* data = (jbyte*)value->base(T_BYTE);
334 return AltHashing::halfsiphash_64(_table->_hash_seed, (const int8_t*)data, length);
326 } 335 }
327 336
328 void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { 337 void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) {
329 assert(java_lang_String::is_instance(java_string), "Must be a string"); 338 assert(java_lang_String::is_instance(java_string), "Must be a string");
330 No_Safepoint_Verifier nsv; 339 No_Safepoint_Verifier nsv;
336 // String has no value 345 // String has no value
337 stat.inc_skipped(); 346 stat.inc_skipped();
338 return; 347 return;
339 } 348 }
340 349
341 unsigned int hash = 0; 350 uint64_t hash = 0;
342 351
343 if (use_java_hash()) { 352 if (use_java_hash()) {
344 // Get hash code from cache 353 // Get hash code from cache
345 hash = java_lang_String::hash(java_string); 354 hash = java_lang_String::hash(java_string);
346 } 355 }
347 356
348 if (hash == 0) { 357 if (hash == 0) {
349 // Compute hash 358 // Compute hash
350 hash = hash_code(value); 359 hash = alt_hash_code(value);
351 stat.inc_hashed(); 360 stat.inc_hashed();
352 } 361 }
353 362
354 if (use_java_hash() && hash != 0) { 363 if (use_java_hash() && hash != 0) {
355 // Store hash code in cache 364 // Store hash code in cache
499 // in the table. We can't transfer entries into the new table 508 // in the table. We can't transfer entries into the new table
500 // at this point since we don't have exclusive access to all 509 // at this point since we don't have exclusive access to all
501 // destination partitions. finish_rehash() will do a single 510 // destination partitions. finish_rehash() will do a single
502 // threaded transfer of all entries. 511 // threaded transfer of all entries.
503 typeArrayOop value = (typeArrayOop)*p; 512 typeArrayOop value = (typeArrayOop)*p;
504 unsigned int hash = hash_code(value); 513 assert(!use_java_hash(), "Should not be using Java hash");
505 (*entry)->set_hash(hash); 514 uint64_t hash = alt_hash_code(value);
515 (*entry)->set_alt_hash(hash);
506 } 516 }
507 517
508 // Move to next entry 518 // Move to next entry
509 entry = (*entry)->next_addr(); 519 entry = (*entry)->next_addr();
510 } 520 }
563 typeArrayOop value = (*entry)->obj(); 573 typeArrayOop value = (*entry)->obj();
564 guarantee(value != NULL, "Object must not be NULL"); 574 guarantee(value != NULL, "Object must not be NULL");
565 guarantee(Universe::heap()->is_in_reserved(value), "Object must be on the heap"); 575 guarantee(Universe::heap()->is_in_reserved(value), "Object must be on the heap");
566 guarantee(!value->is_forwarded(), "Object must not be forwarded"); 576 guarantee(!value->is_forwarded(), "Object must not be forwarded");
567 guarantee(value->is_typeArray(), "Object must be a typeArrayOop"); 577 guarantee(value->is_typeArray(), "Object must be a typeArrayOop");
568 unsigned int hash = hash_code(value); 578 uint64_t hash;
569 guarantee((*entry)->hash() == hash, "Table entry has inorrect hash"); 579 if (use_java_hash()) {
580 hash = (*entry)->java_hash();
581 guarantee(java_hash_code(value) == hash, "Table entry has incorrect hash");
582 } else {
583 hash = (*entry)->alt_hash();
584 guarantee(alt_hash_code(value) == hash, "Table entry has incorrect hash");
585 }
570 guarantee(_table->hash_to_index(hash) == bucket, "Table entry has incorrect index"); 586 guarantee(_table->hash_to_index(hash) == bucket, "Table entry has incorrect index");
571 entry = (*entry)->next_addr(); 587 entry = (*entry)->next_addr();
572 } 588 }
573 589
574 // Verify that we do not have entries with identical oops or identical arrays. 590 // Verify that we do not have entries with identical oops or identical arrays.
579 while (*entry1 != NULL) { 595 while (*entry1 != NULL) {
580 typeArrayOop value1 = (*entry1)->obj(); 596 typeArrayOop value1 = (*entry1)->obj();
581 G1StringDedupEntry** entry2 = (*entry1)->next_addr(); 597 G1StringDedupEntry** entry2 = (*entry1)->next_addr();
582 while (*entry2 != NULL) { 598 while (*entry2 != NULL) {
583 typeArrayOop value2 = (*entry2)->obj(); 599 typeArrayOop value2 = (*entry2)->obj();
584 guarantee(!equals(value1, value2), "Table entries must not have identical arrays"); 600 guarantee(value1 != value2, "Table entries must not have the same array");
601 if (use_java_hash()) {
602 guarantee(!equals(value1, value2), "Table entries must not have identical arrays");
603 }
585 entry2 = (*entry2)->next_addr(); 604 entry2 = (*entry2)->next_addr();
586 } 605 }
587 entry1 = (*entry1)->next_addr(); 606 entry1 = (*entry1)->next_addr();
588 } 607 }
589 } 608 }
598 " [Table]\n" 617 " [Table]\n"
599 " [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]\n" 618 " [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]\n"
600 " [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]\n" 619 " [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]\n"
601 " [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]\n" 620 " [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]\n"
602 " [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]\n" 621 " [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]\n"
603 " [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x]\n" 622 " [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: " UINT64_FORMAT_X "]\n"
604 " [Age Threshold: " UINTX_FORMAT "]", 623 " [Age Threshold: " UINTX_FORMAT "]",
605 G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)), 624 G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)),
606 _table->_size, _min_size, _max_size, 625 _table->_size, _min_size, _max_size,
607 _table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed, 626 _table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed,
608 _resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0, 627 _resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0,

mercurial