8155258: VarHandle implementation improvements
Reviewed-by: shade, vlivanov
This commit is contained in:
parent
0cf5c57454
commit
37445185d2
jdk/src/java.base/share/classes/java/lang/invoke
@ -33,8 +33,6 @@ import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -396,7 +396,7 @@ class Invokers {
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT + 1, names);
|
||||
|
||||
lform.prepare();
|
||||
lform.compileToBytecode();
|
||||
return lform;
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ class Invokers {
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
lform.compileToBytecode();
|
||||
return lform;
|
||||
}
|
||||
|
||||
@ -497,44 +497,33 @@ class Invokers {
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null)
|
||||
throw vh.unsupported();
|
||||
// TODO the following MH is not constant, cache in stable field array
|
||||
// on VarForm?
|
||||
MethodHandle mh = DirectMethodHandle.make(mn);
|
||||
if (actual == expected) {
|
||||
MethodHandle checkVarHandleGenericType(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
// Test for exact match on invoker types
|
||||
// TODO match with erased types and add cast of return value to lambda form
|
||||
MethodHandle mh = handle.getMethodHandle(ad.mode);
|
||||
if (mh.type() == ad.symbolicMethodTypeInvoker) {
|
||||
return mh;
|
||||
}
|
||||
else {
|
||||
// Adapt to the actual (which should never fail since mh's method
|
||||
// type is in the basic form), then to the expected (which my fail
|
||||
// if the symbolic type descriptor does not match)
|
||||
// TODO optimize for the case of actual.erased() == expected.erased()
|
||||
return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
|
||||
asType(expected.insertParameterTypes(0, VarHandle.class));
|
||||
return mh.asType(ad.symbolicMethodTypeInvoker);
|
||||
}
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
if (actual != expected)
|
||||
throw newWrongMethodTypeException(expected, actual);
|
||||
void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
MethodType erasedTarget = handle.vform.methodType_table[ad.type];
|
||||
MethodType erasedSymbolic = ad.symbolicMethodTypeErased;
|
||||
if (erasedTarget != erasedSymbolic)
|
||||
throw newWrongMethodTypeException(erasedTarget, erasedSymbolic);
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
MemberName mn = handle.vform.memberName_table[ad.mode];
|
||||
if (mn == null) {
|
||||
throw vh.unsupported();
|
||||
throw handle.unsupported();
|
||||
}
|
||||
return mn;
|
||||
}
|
||||
|
@ -430,14 +430,14 @@ class MethodHandleNatives {
|
||||
|
||||
// If not polymorphic in the return type, such as the compareAndSet
|
||||
// methods that return boolean
|
||||
if (ak.isPolyMorphicInReturnType) {
|
||||
if (ak.returnType != mtype.returnType()) {
|
||||
if (ak.at.isMonomorphicInReturnType) {
|
||||
if (ak.at.returnType != mtype.returnType()) {
|
||||
// The caller contains a different return type than that
|
||||
// defined by the method
|
||||
throw newNoSuchMethodErrorOnVarHandle(name, mtype);
|
||||
}
|
||||
// Adjust the return type of the signature method type
|
||||
sigType = sigType.changeReturnType(ak.returnType);
|
||||
sigType = sigType.changeReturnType(ak.at.returnType);
|
||||
}
|
||||
|
||||
// Get the guard method type for linking
|
||||
@ -455,26 +455,25 @@ class MethodHandleNatives {
|
||||
MemberName linker = new MemberName(
|
||||
VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
|
||||
guardType, REF_invokeStatic);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
|
||||
linker = MemberName.getFactory().resolveOrNull(REF_invokeStatic, linker,
|
||||
VarHandleGuards.class);
|
||||
if (linker != null) {
|
||||
return linker;
|
||||
}
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
}
|
||||
return Invokers.varHandleInvokeLinkerMethod(name, mtype);
|
||||
}
|
||||
static String getVarHandleMethodSignature(MethodType mt) {
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 2);
|
||||
|
||||
for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
Class<?> pt = mt.parameterType(i);
|
||||
sb.append(getCharType(pt));
|
||||
}
|
||||
|
||||
sb.append('_').append(getCharType(mt.returnType()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
static char getCharType(Class<?> pt) {
|
||||
|
@ -24,42 +24,102 @@
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
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.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A var handle form containing a set of member name, one for each operation.
|
||||
* Each member characterizes a static method.
|
||||
*/
|
||||
class VarForm {
|
||||
final class VarForm {
|
||||
|
||||
// Holds VarForm for VarHandle implementation classes
|
||||
private static final ClassValue<VarForm> VFORMS
|
||||
= new ClassValue<>() {
|
||||
@Override
|
||||
protected VarForm computeValue(Class<?> impl) {
|
||||
return new VarForm(linkFromStatic(impl));
|
||||
final @Stable MethodType[] methodType_table;
|
||||
|
||||
final @Stable MemberName[] memberName_table;
|
||||
|
||||
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
||||
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
||||
|
||||
// TODO lazily calculate
|
||||
this.memberName_table = linkFromStatic(implClass);
|
||||
|
||||
// (Receiver, <Intermediates>)
|
||||
List<Class<?>> l = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
l.add(receiver);
|
||||
l.addAll(Arrays.asList(intermediate));
|
||||
|
||||
// (Receiver, <Intermediates>)Value
|
||||
methodType_table[VarHandle.AccessType.GET.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value)void
|
||||
l.add(value);
|
||||
methodType_table[VarHandle.AccessType.SET.ordinal()] =
|
||||
MethodType.methodType(void.class, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value)Value
|
||||
methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)boolean
|
||||
l.add(value);
|
||||
methodType_table[VarHandle.AccessType.COMPARE_AND_SWAP.ordinal()] =
|
||||
MethodType.methodType(boolean.class, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)Value
|
||||
methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodType getMethodType(int type) {
|
||||
return methodType_table[type];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MemberName getMemberName(int mode) {
|
||||
// TODO calculate lazily
|
||||
MemberName mn = memberName_table[mode];
|
||||
if (mn == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
final @Stable MemberName[] table;
|
||||
|
||||
VarForm(MemberName[] table) {
|
||||
this.table = table;
|
||||
return mn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a var form given an VarHandle implementation class.
|
||||
* Each signature polymorphic method is linked to a static method of the
|
||||
* same name on the implementation class or a super class.
|
||||
*/
|
||||
static VarForm createFromStatic(Class<? extends VarHandle> impl) {
|
||||
return VFORMS.get(impl);
|
||||
|
||||
@Stable
|
||||
MethodType[] methodType_V_table;
|
||||
|
||||
@ForceInline
|
||||
final MethodType[] getMethodType_V_init() {
|
||||
MethodType[] table = new MethodType[VarHandle.AccessType.values().length];
|
||||
for (int i = 0; i < methodType_table.length; i++) {
|
||||
MethodType mt = methodType_table[i];
|
||||
// TODO only adjust for sig-poly methods returning Object
|
||||
table[i] = mt.changeReturnType(void.class);
|
||||
}
|
||||
methodType_V_table = table;
|
||||
return table;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodType getMethodType_V(int type) {
|
||||
MethodType[] table = methodType_V_table;
|
||||
if (table == null) {
|
||||
table = getMethodType_V_init();
|
||||
}
|
||||
return table[type];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Link all signature polymorphic methods.
|
||||
*/
|
||||
|
@ -27,10 +27,9 @@ package java.lang.invoke;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -406,42 +405,10 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
* @since 9
|
||||
*/
|
||||
public abstract class VarHandle {
|
||||
// Use explicit final fields rather than an @Stable array as
|
||||
// this can reduce the memory per handle
|
||||
// e.g. by 24 bytes on 64 bit architectures
|
||||
final MethodType typeGet;
|
||||
final MethodType typeSet;
|
||||
final MethodType typeCompareSwap;
|
||||
final MethodType typeCompareExchange;
|
||||
final MethodType typeGetAndUpdate;
|
||||
|
||||
final VarForm vform;
|
||||
|
||||
VarHandle(VarForm vform, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
||||
VarHandle(VarForm vform) {
|
||||
this.vform = vform;
|
||||
|
||||
// (Receiver, <Intermediates>)
|
||||
List<Class<?>> l = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
l.add(receiver);
|
||||
l.addAll(Arrays.asList(intermediate));
|
||||
|
||||
// (Receiver, <Intermediates>)Value
|
||||
this.typeGet = MethodType.methodType(value, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value)void
|
||||
l.add(value);
|
||||
this.typeSet = MethodType.methodType(void.class, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value)Value
|
||||
this.typeGetAndUpdate = MethodType.methodType(value, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)boolean
|
||||
l.add(value);
|
||||
this.typeCompareSwap = MethodType.methodType(boolean.class, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)Value
|
||||
this.typeCompareExchange = MethodType.methodType(value, l);
|
||||
}
|
||||
|
||||
RuntimeException unsupported() {
|
||||
@ -1090,36 +1057,83 @@ public abstract class VarHandle {
|
||||
Object addAndGet(Object... args);
|
||||
|
||||
enum AccessType {
|
||||
GET, // 0
|
||||
SET, // 1
|
||||
COMPARE_AND_SWAP, // 2
|
||||
COMPARE_AND_EXCHANGE, // 3
|
||||
GET_AND_UPDATE; // 4
|
||||
GET(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(0, receiver, intermediate);
|
||||
fillParameters(ps, receiver, intermediate);
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
},
|
||||
SET(void.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(1, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(void.class, ps);
|
||||
}
|
||||
},
|
||||
COMPARE_AND_SWAP(boolean.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(2, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(boolean.class, ps);
|
||||
}
|
||||
},
|
||||
COMPARE_AND_EXCHANGE(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(2, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
},
|
||||
GET_AND_UPDATE(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(1, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
};
|
||||
|
||||
MethodType getMethodType(VarHandle vh) {
|
||||
return getMethodType(this.ordinal(), vh);
|
||||
final Class<?> returnType;
|
||||
final boolean isMonomorphicInReturnType;
|
||||
|
||||
AccessType(Class<?> returnType) {
|
||||
this.returnType = returnType;
|
||||
isMonomorphicInReturnType = returnType != Object.class;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static MethodType getMethodType(int ordinal, VarHandle vh) {
|
||||
if (ordinal == 0) {
|
||||
return vh.typeGet;
|
||||
}
|
||||
else if (ordinal == 1) {
|
||||
return vh.typeSet;
|
||||
}
|
||||
else if (ordinal == 2) {
|
||||
return vh.typeCompareSwap;
|
||||
}
|
||||
else if (ordinal == 3) {
|
||||
return vh.typeCompareExchange;
|
||||
}
|
||||
else if (ordinal == 4) {
|
||||
return vh.typeGetAndUpdate;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Illegal access type: " + ordinal);
|
||||
}
|
||||
abstract MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate);
|
||||
|
||||
private static Class<?>[] allocateParameters(int values,
|
||||
Class<?> receiver, Class<?>... intermediate) {
|
||||
int size = ((receiver != null) ? 1 : 0) + intermediate.length + values;
|
||||
return new Class<?>[size];
|
||||
}
|
||||
|
||||
private static int fillParameters(Class<?>[] ps,
|
||||
Class<?> receiver, Class<?>... intermediate) {
|
||||
int i = 0;
|
||||
if (receiver != null)
|
||||
ps[i++] = receiver;
|
||||
for (int j = 0; j < intermediate.length; j++)
|
||||
ps[i++] = intermediate[j];
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1133,115 +1147,115 @@ public abstract class VarHandle {
|
||||
* method
|
||||
* {@link VarHandle#get VarHandle.get}
|
||||
*/
|
||||
GET("get", AccessType.GET, Object.class),
|
||||
GET("get", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#set VarHandle.set}
|
||||
*/
|
||||
SET("set", AccessType.SET, void.class),
|
||||
SET("set", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getVolatile VarHandle.getVolatile}
|
||||
*/
|
||||
GET_VOLATILE("getVolatile", AccessType.GET, Object.class),
|
||||
GET_VOLATILE("getVolatile", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setVolatile VarHandle.setVolatile}
|
||||
*/
|
||||
SET_VOLATILE("setVolatile", AccessType.SET, void.class),
|
||||
SET_VOLATILE("setVolatile", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAcquire VarHandle.getAcquire}
|
||||
*/
|
||||
GET_ACQUIRE("getAcquire", AccessType.GET, Object.class),
|
||||
GET_ACQUIRE("getAcquire", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setRelease VarHandle.setRelease}
|
||||
*/
|
||||
SET_RELEASE("setRelease", AccessType.SET, void.class),
|
||||
SET_RELEASE("setRelease", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getOpaque VarHandle.getOpaque}
|
||||
*/
|
||||
GET_OPAQUE("getOpaque", AccessType.GET, Object.class),
|
||||
GET_OPAQUE("getOpaque", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setOpaque VarHandle.setOpaque}
|
||||
*/
|
||||
SET_OPAQUE("setOpaque", AccessType.SET, void.class),
|
||||
SET_OPAQUE("setOpaque", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndSet VarHandle.compareAndSet}
|
||||
*/
|
||||
COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAndSet VarHandle.getAndSet}
|
||||
*/
|
||||
GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class),
|
||||
GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAndAdd VarHandle.getAndAdd}
|
||||
*/
|
||||
GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class),
|
||||
GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#addAndGet VarHandle.addAndGet}
|
||||
*/
|
||||
ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class),
|
||||
ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE),
|
||||
;
|
||||
|
||||
static final Map<String, AccessMode> methodNameToAccessMode;
|
||||
@ -1256,10 +1270,8 @@ public abstract class VarHandle {
|
||||
|
||||
final String methodName;
|
||||
final AccessType at;
|
||||
final boolean isPolyMorphicInReturnType;
|
||||
final Class<?> returnType;
|
||||
|
||||
AccessMode(final String methodName, AccessType at, Class<?> returnType) {
|
||||
AccessMode(final String methodName, AccessType at) {
|
||||
this.methodName = methodName;
|
||||
this.at = at;
|
||||
|
||||
@ -1267,10 +1279,7 @@ public abstract class VarHandle {
|
||||
assert methodName.equals(toMethodName(name()));
|
||||
// Assert that return type is correct
|
||||
// Otherwise, when disabled avoid using reflection
|
||||
assert returnType == getReturnType(methodName);
|
||||
|
||||
this.returnType = returnType;
|
||||
isPolyMorphicInReturnType = returnType != Object.class;
|
||||
assert at.returnType == getReturnType(methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1324,17 +1333,21 @@ public abstract class VarHandle {
|
||||
|
||||
@ForceInline
|
||||
static MemberName getMemberName(int ordinal, VarForm vform) {
|
||||
return vform.table[ordinal];
|
||||
return vform.memberName_table[ordinal];
|
||||
}
|
||||
}
|
||||
|
||||
static final class AccessDescriptor {
|
||||
final MethodType symbolicMethodType;
|
||||
final MethodType symbolicMethodTypeErased;
|
||||
final MethodType symbolicMethodTypeInvoker;
|
||||
final Class<?> returnType;
|
||||
final int type;
|
||||
final int mode;
|
||||
|
||||
public AccessDescriptor(MethodType symbolicMethodType, int type, int mode) {
|
||||
this.symbolicMethodType = symbolicMethodType;
|
||||
this.symbolicMethodTypeErased = symbolicMethodType.erase();
|
||||
this.symbolicMethodTypeInvoker = symbolicMethodType.insertParameterTypes(0, VarHandle.class);
|
||||
this.returnType = symbolicMethodType.returnType();
|
||||
this.type = type;
|
||||
this.mode = mode;
|
||||
}
|
||||
@ -1346,6 +1359,7 @@ public abstract class VarHandle {
|
||||
* @return the variable type of variables referenced by this VarHandle
|
||||
*/
|
||||
public final Class<?> varType() {
|
||||
MethodType typeSet = accessModeType(AccessMode.SET);
|
||||
return typeSet.parameterType(typeSet.parameterCount() - 1);
|
||||
}
|
||||
|
||||
@ -1356,6 +1370,7 @@ public abstract class VarHandle {
|
||||
* list is unmodifiable
|
||||
*/
|
||||
public final List<Class<?>> coordinateTypes() {
|
||||
MethodType typeGet = accessModeType(AccessMode.GET);
|
||||
return typeGet.parameterList();
|
||||
}
|
||||
|
||||
@ -1374,9 +1389,15 @@ public abstract class VarHandle {
|
||||
* @return the access mode type for the given access mode
|
||||
*/
|
||||
public final MethodType accessModeType(AccessMode accessMode) {
|
||||
return accessMode.at.getMethodType(this);
|
||||
TypesAndInvokers tis = getTypesAndInvokers();
|
||||
MethodType mt = tis.methodType_table[accessMode.at.ordinal()];
|
||||
if (mt == null) {
|
||||
mt = tis.methodType_table[accessMode.at.ordinal()] =
|
||||
accessModeTypeUncached(accessMode);
|
||||
}
|
||||
return mt;
|
||||
}
|
||||
|
||||
abstract MethodType accessModeTypeUncached(AccessMode accessMode);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given access mode is supported, otherwise
|
||||
@ -1417,9 +1438,8 @@ public abstract class VarHandle {
|
||||
public final MethodHandle toMethodHandle(AccessMode accessMode) {
|
||||
MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
|
||||
if (mn != null) {
|
||||
return DirectMethodHandle.make(mn).
|
||||
bindTo(this).
|
||||
asType(accessMode.at.getMethodType(this));
|
||||
MethodHandle mh = getMethodHandle(accessMode.ordinal());
|
||||
return mh.bindTo(this);
|
||||
}
|
||||
else {
|
||||
// Ensure an UnsupportedOperationException is thrown
|
||||
@ -1428,6 +1448,51 @@ public abstract class VarHandle {
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
TypesAndInvokers typesAndInvokers;
|
||||
|
||||
static class TypesAndInvokers {
|
||||
final @Stable
|
||||
MethodType[] methodType_table =
|
||||
new MethodType[VarHandle.AccessType.values().length];
|
||||
|
||||
final @Stable
|
||||
MethodHandle[] methodHandle_table =
|
||||
new MethodHandle[AccessMode.values().length];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
private final TypesAndInvokers getTypesAndInvokers() {
|
||||
TypesAndInvokers tis = typesAndInvokers;
|
||||
if (tis == null) {
|
||||
tis = typesAndInvokers = new TypesAndInvokers();
|
||||
}
|
||||
return tis;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodHandle getMethodHandle(int mode) {
|
||||
TypesAndInvokers tis = getTypesAndInvokers();
|
||||
MethodHandle mh = tis.methodHandle_table[mode];
|
||||
if (mh == null) {
|
||||
mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode);
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) {
|
||||
MethodType mt = accessModeType(AccessMode.values()[mode]).
|
||||
insertParameterTypes(0, VarHandle.class);
|
||||
MemberName mn = vform.getMemberName(mode);
|
||||
DirectMethodHandle dmh = DirectMethodHandle.make(mn);
|
||||
// Such a method handle must not be publically exposed directly
|
||||
// otherwise it can be cracked, it must be transformed or rebound
|
||||
// before exposure
|
||||
MethodHandle mh = dmh.copyWith(mt, dmh.form);
|
||||
assert mh.type().erase() == mn.getMethodType().erase();
|
||||
return mh;
|
||||
}
|
||||
|
||||
|
||||
/*non-public*/
|
||||
final void updateVarForm(VarForm newVForm) {
|
||||
if (vform == newVForm) return;
|
||||
@ -1453,6 +1518,10 @@ public abstract class VarHandle {
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw newInternalError(e);
|
||||
}
|
||||
|
||||
// The VarHandleGuards must be initialized to ensure correct
|
||||
// compilation of the guard methods
|
||||
UNSAFE.ensureClassInitialized(VarHandleGuards.class);
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -280,28 +280,29 @@ final class VarHandles {
|
||||
// "@ForceInline\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
|
||||
// " MethodType symbolic = ad.symbolicMethodType;\n" +
|
||||
// " if (target == symbolic) {\n" +
|
||||
// " <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (target.erase() == symbolic.erase()) {\n" +
|
||||
// " if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
|
||||
// " <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
|
||||
// " <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
|
||||
// " <RETURN>mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// "}";
|
||||
//
|
||||
// static final String GET_MEMBER_NAME_METHOD =
|
||||
// static final String GUARD_METHOD_TEMPLATE_V =
|
||||
// "@ForceInline\n" +
|
||||
// "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
|
||||
// " MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
|
||||
// " if (mn == null) {\n" +
|
||||
// " throw handle.unsupported();\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
|
||||
// " MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodType) {\n" +
|
||||
// " MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
|
||||
// " mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " return mn;\n" +
|
||||
// "}";
|
||||
//
|
||||
// // A template for deriving the operations
|
||||
@ -345,8 +346,6 @@ final class VarHandles {
|
||||
// System.out.println("final class VarHandleGuards {");
|
||||
//
|
||||
// System.out.println();
|
||||
// System.out.println(GET_MEMBER_NAME_METHOD);
|
||||
// System.out.println();
|
||||
//
|
||||
// // Declare the stream of shapes
|
||||
// Stream<HandleType> hts = Stream.of(
|
||||
@ -445,7 +444,10 @@ final class VarHandles {
|
||||
//
|
||||
// List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
|
||||
// LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)");
|
||||
// List<String> LINK_TO_STATIC_ARGS_V = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS_V.add("handle.vform.getMemberName_V(ad.mode)");
|
||||
//
|
||||
// List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
@ -464,9 +466,12 @@ final class VarHandles {
|
||||
//
|
||||
// String RETURN_ERASED = returnType != Object.class
|
||||
// ? ""
|
||||
// : " return symbolic.returnType().cast(r);";
|
||||
// : " return ad.returnType.cast(r);";
|
||||
//
|
||||
// return GUARD_METHOD_TEMPLATE.
|
||||
// String template = returnType == void.class
|
||||
// ? GUARD_METHOD_TEMPLATE_V
|
||||
// : GUARD_METHOD_TEMPLATE;
|
||||
// return template.
|
||||
// replace("<METHOD>", METHOD).
|
||||
// replace("<NAME>", NAME).
|
||||
// replaceAll("<RETURN>", RETURN).
|
||||
@ -474,6 +479,8 @@ final class VarHandles {
|
||||
// replace("<RETURN_ERASED>", RETURN_ERASED).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
|
||||
// collect(joining(", "))).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS_V>", LINK_TO_STATIC_ARGS_V.stream().
|
||||
// collect(joining(", "))).
|
||||
// replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
|
||||
// collect(joining(", ")))
|
||||
// ;
|
||||
|
@ -41,12 +41,12 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.FORM);
|
||||
}
|
||||
|
||||
protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldInstanceReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
VarForm form) {
|
||||
super(form);
|
||||
this.fieldOffset = fieldOffset;
|
||||
this.receiverType = receiverType;
|
||||
#if[Object]
|
||||
@ -54,6 +54,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
@ -77,12 +82,14 @@ final class VarHandle$Type$s {
|
||||
return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldInstanceReadOnly.class, Object.class, $type$.class);
|
||||
}
|
||||
|
||||
static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
static final class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
|
||||
FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.FORM);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -202,6 +209,8 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldInstanceReadWrite.class, Object.class, $type$.class);
|
||||
}
|
||||
|
||||
|
||||
@ -213,12 +222,12 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.FORM);
|
||||
}
|
||||
|
||||
protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldStaticReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
|
||||
VarForm form) {
|
||||
super(form);
|
||||
this.base = base;
|
||||
this.fieldOffset = fieldOffset;
|
||||
#if[Object]
|
||||
@ -226,6 +235,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(null, {#if[Object]?fieldType:$type$.class});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$(handle.base,
|
||||
@ -249,12 +263,14 @@ final class VarHandle$Type$s {
|
||||
return UNSAFE.get$Type$Acquire(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldStaticReadOnly.class, null, $type$.class);
|
||||
}
|
||||
|
||||
static class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
static final class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
|
||||
FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.FORM);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -375,6 +391,8 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldStaticReadWrite.class, null, $type$.class);
|
||||
}
|
||||
|
||||
|
||||
@ -387,8 +405,7 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
|
||||
super(VarForm.createFromStatic(Array.class),
|
||||
{#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
super(Array.FORM);
|
||||
this.abase = abase;
|
||||
this.ashift = ashift;
|
||||
#if[Object]
|
||||
@ -397,6 +414,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType({#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
@ -630,5 +652,7 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(Array.class, {#if[Object]?Object[].class:$type$[].class}, {#if[Object]?Object.class:$type$.class}, int.class);
|
||||
}
|
||||
}
|
||||
|
@ -59,13 +59,11 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
#end[floatingPoint]
|
||||
|
||||
|
||||
private static class ByteArrayViewVarHandle extends VarHandle {
|
||||
private static abstract class ByteArrayViewVarHandle extends VarHandle {
|
||||
final boolean be;
|
||||
|
||||
ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
|
||||
Class<?> arrayType, Class<?> component, boolean be) {
|
||||
super(VarForm.createFromStatic(implSubType),
|
||||
arrayType, component, int.class);
|
||||
ByteArrayViewVarHandle(VarForm form, boolean be) {
|
||||
super(form);
|
||||
this.be = be;
|
||||
}
|
||||
}
|
||||
@ -73,7 +71,12 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
static final class ArrayHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ArrayHandle(boolean be) {
|
||||
super(ArrayHandle.class, byte[].class, $type$.class, be);
|
||||
super(ArrayHandle.FORM, be);
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(byte[].class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -286,13 +289,20 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
|
||||
static final class ByteBufferHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ByteBufferHandle(boolean be) {
|
||||
super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
|
||||
super(ByteBufferHandle.FORM, be);
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(ByteBuffer.class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -513,5 +523,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(ByteBufferHandle.class, ByteBuffer.class, $type$.class, int.class);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user