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

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

mercurial