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;
}