< prev index next >

src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java

Print this page
rev 17632 : 8186500: StringConcatFactory.makeConcatWithConstants throws AssertionError when recipe contains non-String constants
Reviewed-by: shade, psandoz

@@ -23,23 +23,28 @@
  * questions.
  */
 
 package java.lang.invoke;
 
+import jdk.internal.misc.Unsafe;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Label;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.vm.annotation.ForceInline;
-import jdk.internal.misc.Unsafe;
+import sun.invoke.util.Wrapper;
+import sun.security.action.GetPropertyAction;
 
 import java.lang.invoke.MethodHandles.Lookup;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
-import sun.security.action.GetPropertyAction;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
 /**
  * <p>Methods to facilitate the creation of String concatenation methods, that

@@ -322,11 +327,16 @@
         private final Object value;
         private final int argPos;
         private final char tag;
 
         public RecipeElement(Object cnst) {
-            this.value = Objects.requireNonNull(cnst);
+            Object value = Objects.requireNonNull(cnst);
+            if (!value.getClass().isPrimitive()) {
+                this.value = String.valueOf(cnst);
+            } else {
+                this.value = value;
+            }
             this.argPos = -1;
             this.tag = TAG_CONST;
         }
 
         public RecipeElement(int arg) {

@@ -922,10 +932,11 @@
 
                 for (RecipeElement el : recipe.getElements()) {
                     switch (el.getTag()) {
                         case TAG_CONST:
                             Object cnst = el.getValue();
+                            String s = (cnst != null) ? cnst.toString() : "null";
                             len += cnst.toString().length();
                             break;
                         case TAG_ARG:
                             /*
                                 If an argument is String, then we can call .length() on it. Sized/Exact modes have

@@ -982,12 +993,13 @@
                 for (RecipeElement el : recipe.getElements()) {
                     String desc;
                     switch (el.getTag()) {
                         case TAG_CONST:
                             Object cnst = el.getValue();
-                            mv.visitLdcInsn(cnst);
-                            desc = getSBAppendDesc(cnst.getClass());
+                            String s = (cnst != null) ? cnst.toString() : "null";
+                            mv.visitLdcInsn(s);
+                            desc = getSBAppendDesc(String.class);
                             break;
                         case TAG_ARG:
                             Class<?> cl = arr[el.getArgPos()];
                             mv.visitVarInsn(getLoadOpcode(cl), off);
                             off += getParameterSize(cl);

@@ -1619,27 +1631,30 @@
 
         // This one is deliberately non-lambdified to optimize startup time:
         private static final Function<Class<?>, MethodHandle> PREPEND = new Function<Class<?>, MethodHandle>() {
             @Override
             public MethodHandle apply(Class<?> c) {
-                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", int.class, int.class, byte[].class, byte.class, c);
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "prepend", int.class, int.class, byte[].class, byte.class,
+                        Wrapper.asPrimitiveType(c));
             }
         };
 
         // This one is deliberately non-lambdified to optimize startup time:
         private static final Function<Class<?>, MethodHandle> CODER_MIX = new Function<Class<?>, MethodHandle>() {
             @Override
             public MethodHandle apply(Class<?> c) {
-                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixCoder", byte.class, byte.class, c);
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixCoder", byte.class, byte.class,
+                        Wrapper.asPrimitiveType(c));
             }
         };
 
         // This one is deliberately non-lambdified to optimize startup time:
         private static final Function<Class<?>, MethodHandle> LENGTH_MIX = new Function<Class<?>, MethodHandle>() {
             @Override
             public MethodHandle apply(Class<?> c) {
-                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixLen", int.class, int.class, c);
+                return lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "mixLen", int.class, int.class,
+                        Wrapper.asPrimitiveType(c));
             }
         };
 
         private static final MethodHandle NEW_STRING;
         private static final MethodHandle NEW_ARRAY;
< prev index next >