8151706: Update VarHandle implementation to use @Stable arrays
Reviewed-by: mhaupt, shade, redestad
This commit is contained in:
parent
589c46da46
commit
878d4d8655
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user