< prev index next >
src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
Print this page
rev 52487 : 8213741: Consolidate Object and String Stringifiers
Reviewed-by: TBD
@@ -1627,11 +1627,11 @@
}
@ForceInline
private static byte[] newArray(long indexCoder) {
byte coder = (byte)(indexCoder >> 32);
- int index = ((int)indexCoder & 0x7FFFFFFF);
+ int index = (int)indexCoder;
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
}
private static MethodHandle prepender(Class<?> cl) {
return PREPENDERS.computeIfAbsent(cl, PREPEND);
@@ -1690,34 +1690,39 @@
private static final class Stringifiers {
private Stringifiers() {
// no instantiation
}
- private static class StringifierMost extends ClassValue<MethodHandle> {
- @Override
- protected MethodHandle computeValue(Class<?> cl) {
- if (cl == String.class) {
- return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, Object.class);
- } else if (cl == float.class) {
- return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, float.class);
- } else if (cl == double.class) {
- return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, double.class);
- } else if (!cl.isPrimitive()) {
- MethodHandle mhObject = lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, Object.class);
-
- // We need the additional conversion here, because String.valueOf(Object) may return null.
- // String conversion rules in Java state we need to produce "null" String in this case.
- // It can be easily done with applying valueOf the second time.
- return MethodHandles.filterReturnValue(mhObject,
- mhObject.asType(MethodType.methodType(String.class, String.class)));
+ private static class StringStringifier {
+
+ // We need some additional conversion for Objects in general, because String.valueOf(Object)
+ // may return null. String conversion rules in Java state we need to produce "null" String
+ // in this case, so we provide a customized version that deals with this problematic corner case.
+ private static String valueOf(Object value) {
+ String s;
+ return (value == null || (s = value.toString()) == null) ? "null" : s;
}
- return null;
+ // Could have used MethodHandles.lookup() instead of Lookup.IMPL_LOOKUP, if not for the fact
+ // java.lang.invoke Lookups are explicitly forbidden to be retrieved using that API.
+ private static final MethodHandle INSTANCE =
+ lookupStatic(Lookup.IMPL_LOOKUP, StringStringifier.class, "valueOf", String.class, Object.class);
+
}
+
+ private static class FloatStringifiers {
+ private static final MethodHandle FLOAT_INSTANCE =
+ lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, float.class);
+
+ private static final MethodHandle DOUBLE_INSTANCE =
+ lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, double.class);
}
private static class StringifierAny extends ClassValue<MethodHandle> {
+
+ private static final ClassValue<MethodHandle> INSTANCE = new StringifierAny();
+
@Override
protected MethodHandle computeValue(Class<?> cl) {
if (cl == byte.class || cl == short.class || cl == int.class) {
return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, int.class);
} else if (cl == boolean.class) {
@@ -1725,42 +1730,46 @@
} else if (cl == char.class) {
return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, char.class);
} else if (cl == long.class) {
return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, long.class);
} else {
- MethodHandle mh = STRINGIFIERS_MOST.get(cl);
+ MethodHandle mh = forMost(cl);
if (mh != null) {
return mh;
} else {
throw new IllegalStateException("Unknown class: " + cl);
}
}
}
}
- private static final ClassValue<MethodHandle> STRINGIFIERS_MOST = new StringifierMost();
- private static final ClassValue<MethodHandle> STRINGIFIERS_ANY = new StringifierAny();
-
/**
* Returns a stringifier for references and floats/doubles only.
* Always returns null for other primitives.
*
* @param t class to stringify
* @return stringifier; null, if not available
*/
static MethodHandle forMost(Class<?> t) {
- return STRINGIFIERS_MOST.get(t);
+ if (!t.isPrimitive()) {
+ return StringStringifier.INSTANCE;
+ } else if (t == float.class) {
+ return FloatStringifiers.FLOAT_INSTANCE;
+ } else if (t == double.class) {
+ return FloatStringifiers.DOUBLE_INSTANCE;
+ }
+ return null;
}
/**
* Returns a stringifier for any type. Never returns null.
*
* @param t class to stringify
* @return stringifier
*/
static MethodHandle forAny(Class<?> t) {
- return STRINGIFIERS_ANY.get(t);
+ return StringifierAny.INSTANCE.get(t);
}
}
/* ------------------------------- Common utilities ------------------------------------ */
< prev index next >