void G1StringDedupTable::deduplicate(oop java_string, G1StringDedupStat& stat) { assert(java_lang_String::is_instance(java_string), "Must be a string"); NoSafepointVerifier nsv; stat.inc_inspected(); typeArrayOop value = java_lang_String::value(java_string); if (value == NULL) { // String has no value stat.inc_skipped(); return; } bool latin1 = java_lang_String::is_latin1(java_string); unsigned int hash = 0; if (use_java_hash()) { // Get hash code from cache hash = java_lang_String::hash(java_string); } if (hash == 0) { // Compute hash hash = hash_code(value, latin1); stat.inc_hashed(); if (use_java_hash() && hash != 0) { // Store hash code in cache java_lang_String::set_hash(java_string, hash); } } typeArrayOop existing_value = lookup_or_add(value, latin1, hash); if (existing_value == value) { // Same value, already known stat.inc_known(); return; } // Get size of value array uintx size_in_bytes = value->size() * HeapWordSize; stat.inc_new(size_in_bytes); if (existing_value != NULL) { // Enqueue the reference to make sure it is kept alive. Concurrent mark might // otherwise declare it dead if there are no other strong references to this object. G1SATBCardTableModRefBS::enqueue(existing_value); // Existing value found, deduplicate string java_lang_String::set_value(java_string, existing_value); if (G1CollectedHeap::heap()->is_in_young(value)) { stat.inc_deduped_young(size_in_bytes); } else { stat.inc_deduped_old(size_in_bytes); } } }
unsigned int G1StringDedupTable::hash_code(typeArrayOop value, bool latin1) { unsigned int hash; int length = value->length(); if (latin1) { const jbyte* data = (jbyte*)value->base(T_BYTE); if (use_java_hash()) { hash = java_lang_String::hash_code(data, length); } else { hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); } } else { length /= sizeof(jchar) / sizeof(jbyte); // Convert number of bytes to number of chars const jchar* data = (jchar*)value->base(T_CHAR); if (use_java_hash()) { hash = java_lang_String::hash_code(data, length); } else { hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); } } return hash; }
unsigned int G1StringDedupTable::hash_code(typeArrayOop value) { unsigned int hash; int length = value->length(); const jchar* data = (jchar*)value->base(T_CHAR); if (use_java_hash()) { hash = java_lang_String::hash_code(data, length); } else { hash = AltHashing::murmur3_32(_table->_hash_seed, data, length); } return hash; }