Remove caching for String.hashcode String hashcode is no longer used in HashMap and it is only used if it is directly called and it doesn't have a predictable performance. I don't see much value in keeping it around any longer. PiperOrigin-RevId: 339796010 Change-Id: I51c45621bea02c48a5b5df316d11a7113643c048
diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java index 45ddd0e..3aba0d3 100644 --- a/user/super/com/google/gwt/emul/java/lang/String.java +++ b/user/super/com/google/gwt/emul/java/lang/String.java
@@ -29,8 +29,8 @@ import java.util.Locale; import java.util.StringJoiner; import javaemul.internal.ArrayHelper; +import javaemul.internal.Coercions; import javaemul.internal.EmulatedCharset; -import javaemul.internal.HashCodes; import javaemul.internal.JsUtils; import javaemul.internal.NativeRegExp; import javaemul.internal.annotations.DoNotInline; @@ -454,7 +454,12 @@ @Override public int hashCode() { - return HashCodes.getStringHashCode(this); + int h = 0; + for (int i = 0; i < length(); i++) { + // Following is the common hash function '(31 * h + x)' as '(x << 5) - x' equal to '31 * x'. + h = Coercions.ensureInt((h << 5) - h + charAt(i)); + } + return h; } public int indexOf(int codePoint) {
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java index 0a50eac..fa7cb68 100644 --- a/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java +++ b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java
@@ -22,7 +22,7 @@ public static int getIdentityHashCode(Object o) { switch (JsUtils.typeOf(o)) { case "string": - return getStringHashCode(JsUtils.uncheckedCast(o)); + return JsUtils.<String>uncheckedCast(o).hashCode(); case "number": return Double.hashCode(JsUtils.unsafeCastToDouble(o)); case "boolean": @@ -35,8 +35,4 @@ public static int getObjectIdentityHashCode(Object o) { return ObjectHashing.getHashCode(o); } - - public static int getStringHashCode(String s) { - return StringHashCache.getHashCode(s); - } }
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java index fa2dca9..efd46f1 100644 --- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java +++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -55,9 +55,5 @@ public static native <T> T getProperty(Object map, String key) /*-{ return map[key]; }-*/; - - public static native void setProperty(Object map, String key, Object value) /*-{ - map[key] = value; - }-*/; }
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java b/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java deleted file mode 100644 index c803422..0000000 --- a/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java +++ /dev/null
@@ -1,97 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package javaemul.internal; - -import static javaemul.internal.Coercions.ensureInt; - -/** - * Hashcode caching for strings. - */ -class StringHashCache { - /** - * The "old" cache; it will be dumped when front is full. - */ - private static Object back = new Object(); - /** - * Tracks the number of entries in front. - */ - private static int count = 0; - /** - * The "new" cache; it will become back when it becomes full. - */ - private static Object front = new Object(); - /** - * Pulled this number out of thin air. - */ - private static final int MAX_CACHE = 256; - - public static int getHashCode(String str) { - // Accesses must to be prefixed with ':' to prevent conflict with built-in - // JavaScript properties. - String key = ":" + str; - - // Check the front store. - Double result = JsUtils.getProperty(front, key); - if (result != null) { - return result.intValue(); - } - // Check the back store. - result = JsUtils.getProperty(back, key); - int hashCode = result == null ? compute(str) : result.intValue(); - // Increment can trigger the swap/flush; call after checking back but - // before writing to front. - increment(); - JsUtils.setProperty(front, key, (double) hashCode); - - return hashCode; - } - - private static int compute(String str) { - int hashCode = 0; - int n = str.length(); - int nBatch = n - 4; - int i = 0; - - // Process batches of 4 characters at a time and add them to the hash coercing to 32 bits - while (i < nBatch) { - hashCode = str.charAt(i + 3) - + 31 * (str.charAt(i + 2) - + 31 * (str.charAt(i + 1) - + 31 * (str.charAt(i) - + 31 * hashCode))); - - hashCode = ensureInt(hashCode); // make sure we don't overflow - i += 4; - } - - // Now process the leftovers - while (i < n) { - hashCode = hashCode * 31 + str.charAt(i++); - } - hashCode = ensureInt(hashCode); // make sure we don't overflow - - return hashCode; - } - - private static void increment() { - if (count == MAX_CACHE) { - back = front; - front = new Object(); - count = 0; - } - ++count; - } -}