< prev index next >

src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java

Print this page
rev 16767 : 8175561: Memory churn in jimage code affects startup after resource encapsulation changes
Reviewed-by: jlaskey
rev 16768 : imported patch imgstr_oneup

@@ -36,10 +36,12 @@
  * but also compiled and delivered as part of the jrtfs.jar to support access
  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public class ImageStringsReader implements ImageStrings {
     public static final int HASH_MULTIPLIER = 0x01000193;
+    public static final int POSITIVE_MASK = 0x7FFFFFFF;
+
     private final BasicImageReader reader;
 
     ImageStringsReader(BasicImageReader reader) {
         this.reader = Objects.requireNonNull(reader);
     }

@@ -52,44 +54,64 @@
     @Override
     public int add(final String string) {
         throw new InternalError("Can not add strings at runtime");
     }
 
-    private static int hashCode(byte[] bytes, int offset, int count, int seed) {
-        Objects.requireNonNull(bytes);
-
-        if (offset < 0 || count < 0 || offset > bytes.length - count) {
-            throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count);
+    public static int hashCode(String string) {
+        return hashCode(string, HASH_MULTIPLIER);
         }
 
-        int limit = offset + count;
-
-        if (limit < 0 || limit > bytes.length) {
-            throw new IndexOutOfBoundsException("limit=" + limit);
+    public static int hashCode(String string, int seed) {
+        return unmaskedHashCode(string, seed) & POSITIVE_MASK;
         }
 
-        for (int i = offset; i < limit; i++) {
-            seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
+    public static int hashCode(String module, String string) {
+        return hashCode(module, string, HASH_MULTIPLIER);
         }
 
-        return seed & 0x7FFFFFFF;
+    public static int hashCode(String module, String string, int seed) {
+        seed = unmaskedHashCode("/", seed);
+        seed = unmaskedHashCode(module, seed);
+        seed = unmaskedHashCode("/", seed);
+        seed = unmaskedHashCode(string, seed);
+        return seed & POSITIVE_MASK;
     }
 
-    public static int hashCode(byte[] bytes, int seed) {
-        return hashCode(bytes, 0, bytes.length, seed);
-    }
+    public static int unmaskedHashCode(String string, int seed) {
+        int slen = string.length();
+        byte[] buffer = null;
 
-    public static int hashCode(byte[] bytes) {
-        return hashCode(bytes, 0, bytes.length, HASH_MULTIPLIER);
-    }
+        for (int i = 0; i < slen; i++) {
+            char ch = string.charAt(i);
+            int uch = ch & 0xFFFF;
 
-    public static int hashCode(String string, int seed) {
-        return hashCode(mutf8FromString(string), seed);
+            if ((uch & ~0x7F) != 0) {
+                if (buffer == null) {
+                    buffer = new byte[8];
     }
+                int mask = ~0x3F;
+                int n = 0;
 
-    public static int hashCode(String string) {
-        return hashCode(mutf8FromString(string), HASH_MULTIPLIER);
+                do {
+                    buffer[n++] = (byte)(0x80 | (uch & 0x3F));
+                    uch >>= 6;
+                    mask >>= 1;
+                } while ((uch & mask) != 0);
+
+                buffer[n] = (byte)((mask << 1) | uch);
+
+                do {
+                    seed = (seed * HASH_MULTIPLIER) ^ (buffer[n--] & 0xFF);
+                } while (0 <= n);
+            } else if (uch == 0) {
+                seed = (seed * HASH_MULTIPLIER) ^ (0xC0);
+                seed = (seed * HASH_MULTIPLIER) ^ (0x80);
+            } else {
+                seed = (seed * HASH_MULTIPLIER) ^ (uch);
+            }
+        }
+        return seed;
     }
 
     static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
         int length = 0;
 

@@ -177,11 +199,11 @@
         }
 
         throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
     }
 
-    static void charsFromByteBuffer(char chars[], ByteBuffer buffer) {
+    static void charsFromByteBuffer(char[] chars, ByteBuffer buffer) {
         int j = 0;
 
         while(buffer.hasRemaining()) {
             byte ch = buffer.get();
 

@@ -226,14 +248,16 @@
         charsFromByteBuffer(chars, buffer);
 
         return new String(chars);
     }
 
-    static int mutf8FromCharsLength(char chars[]) {
+    static int mutf8FromStringLength(String s) {
         int length = 0;
+        int slen = s.length();
 
-        for (char ch : chars) {
+        for (int i = 0; i < slen; i++) {
+            char ch = s.charAt(i);
             int uch = ch & 0xFFFF;
 
             if ((uch & ~0x7F) != 0) {
                 int mask = ~0x3F;
                 int n = 0;

@@ -253,18 +277,23 @@
         }
 
         return length;
     }
 
-    static void mutf8FromChars(byte[] bytes, int offset, char chars[]) {
+    static void mutf8FromString(byte[] bytes, int offset, String s) {
         int j = offset;
-        byte[] buffer = new byte[8];
+        byte[] buffer = null;
+        int slen = s.length();
 
-        for (char ch : chars) {
+        for (int i = 0; i < slen; i++) {
+            char ch = s.charAt(i);
             int uch = ch & 0xFFFF;
 
             if ((uch & ~0x7F) != 0) {
+                if (buffer == null) {
+                    buffer = new byte[8];
+                }
                 int mask = ~0x3F;
                 int n = 0;
 
                 do {
                     buffer[n++] = (byte)(0x80 | (uch & 0x3F));

@@ -285,13 +314,12 @@
             }
         }
     }
 
     public static byte[] mutf8FromString(String string) {
-        char[] chars = string.toCharArray();
-        int length = mutf8FromCharsLength(chars);
+        int length = mutf8FromStringLength(string);
         byte[] bytes = new byte[length];
-        mutf8FromChars(bytes, 0, chars);
+        mutf8FromString(bytes, 0, string);
 
         return bytes;
     }
 }
< prev index next >