# HG changeset patch # User redestad # Date 1465481589 -7200 # Node ID f353ab3063f82a43ef9c4eb1071f2602b4aa1d88 # Parent 84950d65f97a4b203637256601c89ba7a90ec233 8158933: String concat stringifiers setup should avoid unnecessary lookups Reviewed-by: shade diff -r 84950d65f97a -r f353ab3063f8 jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Thu Jun 09 09:33:37 2016 +0200 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Thu Jun 09 16:13:09 2016 +0200 @@ -1733,41 +1733,32 @@ // no instantiation } - // This one is deliberately non-lambdified to optimize startup time: - private static final Function, MethodHandle> MOST = new Function, MethodHandle>() { + private static class StringifierMost extends ClassValue { @Override - public MethodHandle apply(Class cl) { - 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. - MethodHandle mhObjectNoNulls = MethodHandles.filterReturnValue(mhObject, - mhObject.asType(MethodType.methodType(String.class, String.class))); - + protected MethodHandle computeValue(Class cl) { if (cl == String.class) { - return mhObject; + 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()) { - return mhObjectNoNulls; + 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))); } return null; } - }; + } - // This one is deliberately non-lambdified to optimize startup time: - private static final Function, MethodHandle> ANY = new Function, MethodHandle>() { + private static class StringifierAny extends ClassValue { @Override - public MethodHandle apply(Class cl) { - MethodHandle mh = MOST.apply(cl); - if (mh != null) { - return mh; - } - + 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) { @@ -1777,13 +1768,18 @@ } else if (cl == long.class) { return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, long.class); } else { - throw new IllegalStateException("Unknown class: " + cl); + MethodHandle mh = STRINGIFIERS_MOST.get(cl); + if (mh != null) { + return mh; + } else { + throw new IllegalStateException("Unknown class: " + cl); + } } } - }; + } - private static final ConcurrentMap, MethodHandle> STRINGIFIERS_MOST = new ConcurrentHashMap<>(); - private static final ConcurrentMap, MethodHandle> STRINGIFIERS_ANY = new ConcurrentHashMap<>(); + private static final ClassValue STRINGIFIERS_MOST = new StringifierMost(); + private static final ClassValue STRINGIFIERS_ANY = new StringifierAny(); /** * Returns a stringifier for references and floats/doubles only. @@ -1793,7 +1789,7 @@ * @return stringifier; null, if not available */ static MethodHandle forMost(Class t) { - return STRINGIFIERS_MOST.computeIfAbsent(t, MOST); + return STRINGIFIERS_MOST.get(t); } /** @@ -1803,7 +1799,7 @@ * @return stringifier */ static MethodHandle forAny(Class t) { - return STRINGIFIERS_ANY.computeIfAbsent(t, ANY); + return STRINGIFIERS_ANY.get(t); } }