8151706: Update VarHandle implementation to use @Stable arrays
Reviewed-by: mhaupt, shade, redestad
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java Mon Apr 11 10:55:03 2016 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java Mon Apr 11 18:21:25 2016 +0200
@@ -24,16 +24,11 @@
*/
package java.lang.invoke;
+import jdk.internal.vm.annotation.Stable;
+
import java.lang.invoke.VarHandle.AccessMode;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-
-import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
/**
* A var handle form containing a set of member name, one for each operation.
@@ -43,51 +38,17 @@
// Holds VarForm for VarHandle implementation classes
private static final ClassValue<VarForm> VFORMS
- = new ClassValue<VarForm>() {
+ = new ClassValue<>() {
@Override
protected VarForm computeValue(Class<?> impl) {
- return new VarForm(link(staticMethodLinker(impl)));
+ return new VarForm(linkFromStatic(impl));
}
};
- final MemberName mbGet;
- final MemberName mbSet;
- final MemberName mbGetVolatile;
- final MemberName mbSetVolatile;
- final MemberName mbGetAcquire;
- final MemberName mbSetRelease;
- final MemberName mbCompareAndSet;
- final MemberName mbCompareAndExchangeVolatile;
- final MemberName mbCompareAndExchangeAcquire;
- final MemberName mbCompareAndExchangeRelease;
- final MemberName mbWeakCompareAndSet;
- final MemberName mbWeakCompareAndSetAcquire;
- final MemberName mbWeakCompareAndSetRelease;
- final MemberName mbGetAndSet;
- final MemberName mbGetAndAdd;
- final MemberName mbAddAndGet;
- final MemberName mbGetOpaque;
- final MemberName mbSetOpaque;
+ final @Stable MemberName[] table;
- VarForm(Map<AccessMode, MemberName> linkMap) {
- mbGet = linkMap.get(AccessMode.get);
- mbSet = linkMap.get(AccessMode.set);
- mbGetVolatile = linkMap.get(AccessMode.getVolatile);
- mbSetVolatile = linkMap.get(AccessMode.setVolatile);
- mbGetOpaque = linkMap.get(AccessMode.getOpaque);
- mbSetOpaque = linkMap.get(AccessMode.setOpaque);
- mbGetAcquire = linkMap.get(AccessMode.getAcquire);
- mbSetRelease = linkMap.get(AccessMode.setRelease);
- mbCompareAndSet = linkMap.get(AccessMode.compareAndSet);
- mbCompareAndExchangeVolatile = linkMap.get(AccessMode.compareAndExchangeVolatile);
- mbCompareAndExchangeAcquire = linkMap.get(AccessMode.compareAndExchangeAcquire);
- mbCompareAndExchangeRelease = linkMap.get(AccessMode.compareAndExchangeRelease);
- mbWeakCompareAndSet = linkMap.get(AccessMode.weakCompareAndSet);
- mbWeakCompareAndSetAcquire = linkMap.get(AccessMode.weakCompareAndSetAcquire);
- mbWeakCompareAndSetRelease = linkMap.get(AccessMode.weakCompareAndSetRelease);
- mbGetAndSet = linkMap.get(AccessMode.getAndSet);
- mbGetAndAdd = linkMap.get(AccessMode.getAndAdd);
- mbAddAndGet = linkMap.get(AccessMode.addAndGet);
+ VarForm(MemberName[] table) {
+ this.table = table;
}
/**
@@ -102,63 +63,23 @@
/**
* Link all signature polymorphic methods.
*/
- private static Map<AccessMode, MemberName> link(Function<AccessMode, MemberName> linker) {
- Map<AccessMode, MemberName> links = new HashMap<>();
- for (AccessMode ak : AccessMode.values()) {
- links.put(ak, linker.apply(ak));
- }
- return links;
- }
-
+ private static MemberName[] linkFromStatic(Class<?> implClass) {
+ MemberName[] table = new MemberName[AccessMode.values().length];
- /**
- * Returns a function that associates an AccessMode with a MemberName that
- * is a static concrete method implementation for the access operation of
- * the implementing class.
- */
- private static Function<AccessMode, MemberName> staticMethodLinker(Class<?> implClass) {
- // Find all declared static methods on the implementation class and
- // all super classes up to but not including VarHandle
- List<Method> staticMethods = new ArrayList<>(AccessMode.values().length);
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
for (Method m : c.getDeclaredMethods()) {
if (Modifier.isStatic(m.getModifiers())) {
- staticMethods.add(m);
+ try {
+ AccessMode am = AccessMode.valueOf(m.getName());
+ assert table[am.ordinal()] == null;
+ table[am.ordinal()] = new MemberName(m);
+ } catch (IllegalArgumentException ex) {
+ // Ignore. Note the try/catch will be removed when
+ // AccessMode enum constant names are renamed
+ }
}
}
}
-
- // This needs to be an anonymous inner class and not a lambda expression
- // The latter will cause the intialization of classes in java.lang.invoke
- // resulting in circular dependencies if VarHandles are utilized early
- // in the start up process. For example, if ConcurrentHashMap
- // is modified to use VarHandles.
- return new Function<>() {
- @Override
- public MemberName apply(AccessMode ak) {
- Method m = null;
- for (Method to_m : staticMethods) {
- if (to_m.getName().equals(ak.name()) &&
- Modifier.isStatic(to_m.getModifiers())) {
- assert m == null : String.format(
- "Two or more static methods named %s are present on " +
- "class %s or a super class", ak.name(), implClass.getName());
- m = to_m;
- }
- }
-
- if (m == null)
- return null;
-
- MemberName linkedMethod = new MemberName(m);
- try {
- return MemberName.getFactory().resolveOrFail(
- REF_invokeStatic, linkedMethod, m.getDeclaringClass(), NoSuchMethodException.class);
- }
- catch (ReflectiveOperationException e) {
- throw new InternalError(e);
- }
- }
- };
+ return table;
}
-}
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Mon Apr 11 10:55:03 2016 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Mon Apr 11 18:21:25 2016 +0200
@@ -1168,63 +1168,7 @@
@ForceInline
static MemberName getMemberName(int ordinal, VarForm vform) {
- if (ordinal == 0) {
- return vform.mbGet;
- }
- else if (ordinal == 1) {
- return vform.mbSet;
- }
- else if (ordinal == 2) {
- return vform.mbGetVolatile;
- }
- else if (ordinal == 3) {
- return vform.mbSetVolatile;
- }
- else if (ordinal == 4) {
- return vform.mbGetAcquire;
- }
- else if (ordinal == 5) {
- return vform.mbSetRelease;
- }
- else if (ordinal == 6) {
- return vform.mbGetOpaque;
- }
- else if (ordinal == 7) {
- return vform.mbSetOpaque;
- }
- else if (ordinal == 8) {
- return vform.mbCompareAndSet;
- }
- else if (ordinal == 9) {
- return vform.mbCompareAndExchangeVolatile;
- }
- else if (ordinal == 10) {
- return vform.mbCompareAndExchangeAcquire;
- }
- else if (ordinal == 11) {
- return vform.mbCompareAndExchangeRelease;
- }
- else if (ordinal == 12) {
- return vform.mbWeakCompareAndSet;
- }
- else if (ordinal == 13) {
- return vform.mbWeakCompareAndSetAcquire;
- }
- else if (ordinal == 14) {
- return vform.mbWeakCompareAndSetRelease;
- }
- else if (ordinal == 15) {
- return vform.mbGetAndSet;
- }
- else if (ordinal == 16) {
- return vform.mbGetAndAdd;
- }
- else if (ordinal == 17) {
- return vform.mbAddAndGet;
- }
- else {
- throw new IllegalStateException("Illegal access mode: " + ordinal);
- }
+ return vform.table[ordinal];
}
}