mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8318776: Require supports_cx8 to always be true
Reviewed-by: eosterlund, shade, dcubed
This commit is contained in:
parent
14557e72ef
commit
c75c38871e
39 changed files with 31 additions and 444 deletions
|
@ -55,20 +55,6 @@ import jdk.internal.misc.Unsafe;
|
|||
public class AtomicLong extends Number implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 1927816293512124184L;
|
||||
|
||||
/**
|
||||
* Records whether the underlying JVM supports lockless
|
||||
* compareAndSet for longs. While the intrinsic compareAndSetLong
|
||||
* method works in either case, some constructions should be
|
||||
* handled at Java level to avoid locking user-visible locks.
|
||||
*/
|
||||
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
|
||||
|
||||
/**
|
||||
* Returns whether underlying JVM supports lockless CompareAndSet
|
||||
* for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
|
||||
*/
|
||||
private static native boolean VMSupportsCS8();
|
||||
|
||||
/*
|
||||
* This class intended to be implemented using VarHandles, but there
|
||||
* are unresolved cyclic startup dependencies.
|
||||
|
|
|
@ -90,10 +90,7 @@ public abstract class AtomicLongFieldUpdater<T> {
|
|||
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
|
||||
String fieldName) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
|
||||
return new CASUpdater<U>(tclass, fieldName, caller);
|
||||
else
|
||||
return new LockedUpdater<U>(tclass, fieldName, caller);
|
||||
return new CASUpdater<U>(tclass, fieldName, caller);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -515,126 +512,6 @@ public abstract class AtomicLongFieldUpdater<T> {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
private final long offset;
|
||||
/**
|
||||
* if field is protected, the subclass constructing updater, else
|
||||
* the same as tclass
|
||||
*/
|
||||
private final Class<?> cclass;
|
||||
/** class holding the field */
|
||||
private final Class<T> tclass;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
LockedUpdater(final Class<T> tclass, final String fieldName,
|
||||
final Class<?> caller) {
|
||||
final Field field;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Field>() {
|
||||
public Field run() throws NoSuchFieldException {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
ClassLoader cl = tclass.getClassLoader();
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if ((ccl != null) && (ccl != cl) &&
|
||||
((cl == null) || !isAncestor(cl, ccl))) {
|
||||
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
|
||||
}
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new RuntimeException(pae.getException());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
if (field.getType() != long.class)
|
||||
throw new IllegalArgumentException("Must be long type");
|
||||
|
||||
if (!Modifier.isVolatile(modifiers))
|
||||
throw new IllegalArgumentException("Must be volatile type");
|
||||
|
||||
// Access to protected field members is restricted to receivers only
|
||||
// of the accessing class, or one of its subclasses, and the
|
||||
// accessing class must in turn be a subclass (or package sibling)
|
||||
// of the protected member's defining class.
|
||||
// If the updater refers to a protected field of a declaring class
|
||||
// outside the current package, the receiver argument will be
|
||||
// narrowed to the type of the accessing class.
|
||||
this.cclass = (Modifier.isProtected(modifiers) &&
|
||||
tclass.isAssignableFrom(caller) &&
|
||||
!isSamePackage(tclass, caller))
|
||||
? caller : tclass;
|
||||
this.tclass = tclass;
|
||||
this.offset = U.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that target argument is instance of cclass. On
|
||||
* failure, throws cause.
|
||||
*/
|
||||
private final void accessCheck(T obj) {
|
||||
if (!cclass.isInstance(obj))
|
||||
throw accessCheckException(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns access exception if accessCheck failed due to
|
||||
* protected access, else ClassCastException.
|
||||
*/
|
||||
private final RuntimeException accessCheckException(T obj) {
|
||||
if (cclass == tclass)
|
||||
return new ClassCastException();
|
||||
else
|
||||
return new RuntimeException(
|
||||
new IllegalAccessException(
|
||||
"Class " +
|
||||
cclass.getName() +
|
||||
" can not access a protected member of class " +
|
||||
tclass.getName() +
|
||||
" using an instance of " +
|
||||
obj.getClass().getName()));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(T obj, long expect, long update) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
long v = U.getLong(obj, offset);
|
||||
if (v != expect)
|
||||
return false;
|
||||
U.putLong(obj, offset, update);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(T obj, long expect, long update) {
|
||||
return compareAndSet(obj, expect, update);
|
||||
}
|
||||
|
||||
public final void set(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
U.putLong(obj, offset, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public final void lazySet(T obj, long newValue) {
|
||||
set(obj, newValue);
|
||||
}
|
||||
|
||||
public final long get(T obj) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
return U.getLong(obj, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the second classloader can be found in the first
|
||||
* classloader's delegation chain.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue