8148869: StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
authorshade
Wed, 03 Feb 2016 00:49:41 +0300
changeset 35700 b933119b8f84
parent 35699 2a610264e6fc
child 35701 d5a24d2b0494
8148869: StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings Reviewed-by: vlivanov, psandoz
jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java
jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
jdk/test/java/lang/String/concat/CompactStringsInitialCoder.java
--- a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java	Tue Feb 02 13:42:48 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java	Wed Feb 03 00:49:41 2016 +0300
@@ -342,4 +342,12 @@
         return new String(buf, coder);
     }
 
+    /**
+     * Provides the initial coder for the String.
+     * @return initial coder
+     */
+    static byte initialCoder() {
+        return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16;
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Tue Feb 02 13:42:48 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Wed Feb 03 00:49:41 2016 +0300
@@ -30,7 +30,7 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.vm.annotation.ForceInline;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import java.lang.invoke.MethodHandles.Lookup;
 import java.security.AccessController;
@@ -1497,7 +1497,7 @@
             //
             // The method handle shape after all length and coder mixers is:
             //   (int, byte, <args>)String = ("index", "coder", <args>)
-            byte initialCoder = 0; // initial coder
+            byte initialCoder = INITIAL_CODER;
             int initialLen = 0;    // initial length, in characters
             for (RecipeElement el : recipe.getElements()) {
                 switch (el.getTag()) {
@@ -1630,11 +1630,14 @@
         private static final ConcurrentMap<Class<?>, MethodHandle> LENGTH_MIXERS;
         private static final ConcurrentMap<Class<?>, MethodHandle> CODER_MIXERS;
         private static final Class<?> STRING_HELPER;
+        private static final byte INITIAL_CODER;
 
         static {
             try {
                 STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
-            } catch (ClassNotFoundException e) {
+                MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", byte.class);
+                INITIAL_CODER = (byte) initCoder.invoke();
+            } catch (Throwable e) {
                 throw new AssertionError(e);
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/concat/CompactStringsInitialCoder.java	Wed Feb 03 00:49:41 2016 +0300
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
+ * @bug 8148869
+ *
+ * @compile -XDstringConcat=indy -source 1.9 -target 1.9 CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:+CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:+CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indy -source 1.9 -target 1.9 CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:-CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:-CompactStrings   CompactStringsInitialCoder
+*/
+import java.lang.StringBuilder;
+
+public class CompactStringsInitialCoder {
+
+    static String strEmpty   = "";
+    static String strLatin1  = "\u0042";
+    static String strUTF16   = "\u4242";
+    static char   charLatin1 = '\u0042';
+    static char   charUTF16  = '\u4242';
+
+    public static void main(String[] args) throws Exception {
+        test("\u0042", "" + '\u0042');
+        test("\u4242", "" + '\u4242');
+
+        test("\u0042", "" + charLatin1);
+        test("\u4242", "" + charUTF16);
+
+        test("\u0042", strEmpty + '\u0042');
+        test("\u4242", strEmpty + '\u4242');
+
+        test("\u0042\u0042", strLatin1 + '\u0042');
+        test("\u0042\u4242", strLatin1 + '\u4242');
+        test("\u4242\u0042", strUTF16  + '\u0042');
+        test("\u4242\u4242", strUTF16  + '\u4242');
+
+        test("\u0042\u0042", "\u0042" + charLatin1);
+        test("\u0042\u4242", "\u0042" + charUTF16);
+        test("\u4242\u0042", "\u4242" + charLatin1);
+        test("\u4242\u4242", "\u4242" + charUTF16);
+
+        test("\u0042\u0042", "" + charLatin1 + charLatin1);
+        test("\u0042\u4242", "" + charLatin1 + charUTF16);
+        test("\u4242\u0042", "" + charUTF16  + charLatin1);
+        test("\u4242\u4242", "" + charUTF16  + charUTF16);
+    }
+
+    public static void test(String expected, String actual) {
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+
+
+}