< prev index next >
src/java.base/share/classes/sun/invoke/util/ValueConversions.java
Print this page
rev 15320 : 8163370: Reduce number of classes loaded by common usage of java.lang.invoke
Reviewed-by: igerasim, psandoz
*** 27,59 ****
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
! import java.util.EnumMap;
public class ValueConversions {
private static final Class<?> THIS_CLASS = ValueConversions.class;
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
! /** Thread-safe canonicalized mapping from Wrapper to MethodHandle
* with unsynchronized reads and synchronized writes.
! * It's safe to publish MethodHandles by data race because they are immutable. */
private static class WrapperCache {
! /** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */
! private final EnumMap<Wrapper, MethodHandle> map = new EnumMap<>(Wrapper.class);
public MethodHandle get(Wrapper w) {
! return map.get(w);
}
public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
! // Simulate CAS to avoid racy duplication
! MethodHandle prev = map.putIfAbsent(w, mh);
! if (prev != null) return prev;
return mh;
}
}
private static WrapperCache[] newWrapperCaches(int n) {
WrapperCache[] caches = new WrapperCache[n];
for (int i = 0; i < n; i++)
caches[i] = new WrapperCache();
--- 27,64 ----
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
! import jdk.internal.vm.annotation.Stable;
public class ValueConversions {
private static final Class<?> THIS_CLASS = ValueConversions.class;
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
! /**
! * Thread-safe canonicalized mapping from Wrapper to MethodHandle
* with unsynchronized reads and synchronized writes.
! * It's safe to publish MethodHandles by data race because they are immutable.
! */
private static class WrapperCache {
! @Stable
! private final MethodHandle[] map = new MethodHandle[Wrapper.COUNT];
public MethodHandle get(Wrapper w) {
! return map[w.ordinal()];
}
public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
! MethodHandle prev = map[w.ordinal()];
! if (prev != null) {
! return prev;
! } else {
! map[w.ordinal()] = mh;
return mh;
}
}
+ }
private static WrapperCache[] newWrapperCaches(int n) {
WrapperCache[] caches = new WrapperCache[n];
for (int i = 0; i < n; i++)
caches[i] = new WrapperCache();
*** 621,631 ****
static byte fromBoolean(boolean x) {
// see javadoc for MethodHandles.explicitCastArguments
return (x ? (byte)1 : (byte)0);
}
! private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
MethodHandle mh = cache.get(wdst);
if (mh != null) {
--- 626,636 ----
static byte fromBoolean(boolean x) {
// see javadoc for MethodHandles.explicitCastArguments
return (x ? (byte)1 : (byte)0);
}
! private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.COUNT);
public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
MethodHandle mh = cache.get(wdst);
if (mh != null) {
< prev index next >