< prev index next > src/java.base/share/classes/java/lang/invoke/VarHandles.java
Print this page
*/
package java.lang.invoke;
import jdk.internal.misc.CDS;
+ import jdk.internal.value.ValueClass;
+ import jdk.internal.vm.annotation.LooselyConsistentValue;
import sun.invoke.util.Wrapper;
import java.lang.foreign.MemoryLayout;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
if (!f.isStatic()) {
long foffset = MethodHandleNatives.objectFieldOffset(f);
Class<?> type = f.getFieldType();
if (!type.isPrimitive()) {
! return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
! ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
! : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));
}
else if (type == boolean.class) {
return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
: new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
if (!f.isStatic()) {
long foffset = MethodHandleNatives.objectFieldOffset(f);
Class<?> type = f.getFieldType();
if (!type.isPrimitive()) {
! if (type.isValue()) {
! int layout = f.getLayout();
! boolean isAtomic = isAtomicFlat(f);
+ boolean isFlat = f.isFlat();
+ if (isFlat) {
+ if (isAtomic) {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleFlatValues.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted(), layout)
+ : new VarHandleFlatValues.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted(), layout));
+ } else {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleNonAtomicFlatValues.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted(), layout)
+ : new VarHandleNonAtomicFlatValues.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted(), layout));
+ }
+ } else {
+ if (isAtomic) {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
+ : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
+ } else {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleNonAtomicReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
+ : new VarHandleNonAtomicReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
+ }
+ }
+ } else {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
+ : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
+ }
}
else if (type == boolean.class) {
return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
: new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
Object base = MethodHandleNatives.staticFieldBase(f);
long foffset = MethodHandleNatives.staticFieldOffset(f);
Class<?> type = f.getFieldType();
if (!type.isPrimitive()) {
! return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
! ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
! : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));
}
else if (type == boolean.class) {
return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
: new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
Object base = MethodHandleNatives.staticFieldBase(f);
long foffset = MethodHandleNatives.staticFieldOffset(f);
Class<?> type = f.getFieldType();
if (!type.isPrimitive()) {
! assert !f.isFlat() : ("static field is flat in " + decl + "." + f.getName());
! if (type.isValue()) {
! if (isAtomicFlat(f)) {
+ return f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
+ : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
+ } else {
+ return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleNonAtomicReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
+ : new VarHandleNonAtomicReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted()));
+ }
+ } else {
+ return f.isFinal() && !isWriteAllowedOnFinalFields
+ ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
+ : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
+ }
}
else if (type == boolean.class) {
return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
: new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
else {
throw new UnsupportedOperationException();
}
}
+ static boolean isAtomicFlat(MemberName field) {
+ boolean hasAtomicAccess = (field.getModifiers() & Modifier.VOLATILE) != 0 ||
+ !(field.isNullRestricted()) ||
+ !field.getFieldType().isAnnotationPresent(LooselyConsistentValue.class);
+ return hasAtomicAccess && !HAS_OOPS.get(field.getFieldType());
+ }
+
+ static boolean isAtomicFlat(Object[] array) {
+ Class<?> componentType = array.getClass().componentType();
+ boolean hasAtomicAccess = ValueClass.isAtomicArray(array) ||
+ !ValueClass.isNullRestrictedArray(array) ||
+ !componentType.isAnnotationPresent(LooselyConsistentValue.class);
+ return hasAtomicAccess && !HAS_OOPS.get(componentType);
+ }
+
+ static final ClassValue<Boolean> HAS_OOPS = new ClassValue<>() {
+ @Override
+ protected Boolean computeValue(Class<?> c) {
+ for (Field f : c.getDeclaredFields()) {
+ Class<?> ftype = f.getType();
+ if (UNSAFE.isFlatField(f) && HAS_OOPS.get(ftype)) {
+ return true;
+ } else if (!ftype.isPrimitive()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
// Required by instance field handles
static Field getFieldFromReceiverAndOffset(Class<?> receiverType,
long offset,
Class<?> fieldType) {
for (Field f : receiverType.getDeclaredFields()) {
}
}
throw new InternalError("Static field not found at offset");
}
+ // This is invoked by non-flat array var handle code when attempting to access a flat array
+ public static void checkAtomicFlatArray(Object[] array) {
+ if (!isAtomicFlat(array)) {
+ throw new IllegalArgumentException("Attempt to perform a non-plain access on a non-atomic array");
+ }
+ }
+
static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
if (!arrayClass.isArray())
throw new IllegalArgumentException("not an array: " + arrayClass);
Class<?> componentType = arrayClass.getComponentType();
int aoffset = (int) UNSAFE.arrayBaseOffset(arrayClass);
int ascale = UNSAFE.arrayIndexScale(arrayClass);
int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
if (!componentType.isPrimitive()) {
+ // Here we always return a reference array element var handle. This is because
+ // the access semantics is determined at runtime, when an actual array object is passed
+ // to the var handle. The var handle implementation will switch to use flat access
+ // primitives if it sees a flat array.
return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));
}
else if (componentType == boolean.class) {
return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
}
< prev index next >