changeset 37172:ff4d69314a4c

8144940: Broken hash in string table entry in closed/runtime/7158800/BadUtf8.java Summary: Fix code broken with compact Strings. Reviewed-by: iklam, thartmann, hseigel, jiangli
author coleenp
date Tue, 22 Mar 2016 13:32:18 -0400
parents b968bbc6291c
children 52450946e39e
files hotspot/src/share/vm/classfile/javaClasses.cpp hotspot/src/share/vm/classfile/javaClasses.hpp hotspot/src/share/vm/classfile/stringTable.cpp hotspot/src/share/vm/classfile/stringTable.hpp
diffstat 4 files changed, 22 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Tue Mar 22 13:41:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Tue Mar 22 13:32:18 2016 -0400
@@ -513,21 +513,6 @@
   return result;
 }
 
-unsigned int java_lang_String::hash_string(oop java_string) {
-  int          length = java_lang_String::length(java_string);
-  // Zero length string doesn't necessarily hash to zero.
-  if (length == 0) {
-    return StringTable::hash_string((jchar*) NULL, 0);
-  }
-
-  typeArrayOop value  = java_lang_String::value(java_string);
-  bool      is_latin1 = java_lang_String::is_latin1(java_string);
-  if (is_latin1) {
-    return StringTable::hash_string(value->byte_at_addr(0), length);
-  } else {
-    return StringTable::hash_string(value->char_at_addr(0), length);
-  }
-}
 
 Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
   oop          obj    = java_string();
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Tue Mar 22 13:41:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Tue Mar 22 13:32:18 2016 -0400
@@ -155,11 +155,6 @@
   }
 
   static unsigned int hash_code(oop java_string);
-  static unsigned int latin1_hash_code(typeArrayOop value, int len);
-
-  // This is the string hash code used by the StringTable, which may be
-  // the same as String.hashCode or an alternate hash code.
-  static unsigned int hash_string(oop java_string);
 
   static bool equals(oop java_string, jchar* chars, int len);
   static bool equals(oop str1, oop str2);
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Tue Mar 22 13:41:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Tue Mar 22 13:32:18 2016 -0400
@@ -94,15 +94,27 @@
 CompactHashtable<oop, char> StringTable::_shared_table;
 
 // Pick hashing algorithm
-template<typename T>
-unsigned int StringTable::hash_string(const T* s, int len) {
+unsigned int StringTable::hash_string(const jchar* s, int len) {
   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
                                     java_lang_String::hash_code(s, len);
 }
 
-// Explicit instantiation for all supported types.
-template unsigned int StringTable::hash_string<jchar>(const jchar* s, int len);
-template unsigned int StringTable::hash_string<jbyte>(const jbyte* s, int len);
+unsigned int StringTable::hash_string(oop string) {
+  EXCEPTION_MARK;
+  if (string == NULL) {
+    return hash_string((jchar*)NULL, 0);
+  }
+  ResourceMark rm(THREAD);
+  // All String oops are hashed as unicode
+  int length;
+  jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD);
+  if (chars != NULL) {
+    return hash_string(chars, length);
+  } else {
+    vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification");
+    return 0;
+  }
+}
 
 oop StringTable::lookup_shared(jchar* name, int len) {
   // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't
@@ -398,7 +410,7 @@
     for ( ; p != NULL; p = p->next()) {
       oop s = p->literal();
       guarantee(s != NULL, "interned string is NULL");
-      unsigned int h = java_lang_String::hash_string(s);
+      unsigned int h = hash_string(s);
       guarantee(p->hash() == h, "broken hash in string table entry");
       guarantee(the_table()->hash_to_index(h) == i,
                 "wrong index in string table");
@@ -498,7 +510,7 @@
     return _verify_fail_done;
   }
 
-  unsigned int h = java_lang_String::hash_string(str);
+  unsigned int h = hash_string(str);
   if (e_ptr->hash() != h) {
     if (mesg_mode == _verify_with_mesgs) {
       tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], "
--- a/hotspot/src/share/vm/classfile/stringTable.hpp	Tue Mar 22 13:41:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Tue Mar 22 13:32:18 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,8 @@
   // Hashing algorithm, used as the hash value used by the
   //     StringTable for bucket selection and comparison (stored in the
   //     HashtableEntry structures).  This is used in the String.intern() method.
-  template<typename T> static unsigned int hash_string(const T* s, int len);
+  static unsigned int hash_string(const jchar* s, int len);
+  static unsigned int hash_string(oop string);
 
   // Internal test.
   static void test_alt_hash() PRODUCT_RETURN;