8151706: Update VarHandle implementation to use @Stable arrays

Reviewed-by: mhaupt, shade, redestad
This commit is contained in:
Paul Sandoz 2016-04-11 18:21:25 +02:00
parent 589c46da46
commit 878d4d8655
2 changed files with 20 additions and 155 deletions

View File

@ -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 @@ class VarForm {
// 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 @@ class VarForm {
/**
* 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;
}
}
}

View File

@ -1168,63 +1168,7 @@ public abstract class VarHandle {
@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];
}
}