8273000: Remove WeakReference-based class initialisation barrier implementation
Reviewed-by: psandoz, mchung
This commit is contained in:
parent
21012f2bbe
commit
faa942c8ba
src/java.base/share/classes
@ -33,7 +33,6 @@ import sun.invoke.util.VerifyAccess;
|
||||
import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
@ -363,27 +362,12 @@ class DirectMethodHandle extends MethodHandle {
|
||||
VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
|
||||
// It is a system class. It is probably in the process of
|
||||
// being initialized, but we will help it along just to be safe.
|
||||
if (UNSAFE.shouldBeInitialized(cls)) {
|
||||
UNSAFE.ensureClassInitialized(cls);
|
||||
}
|
||||
UNSAFE.ensureClassInitialized(cls);
|
||||
return false;
|
||||
}
|
||||
return UNSAFE.shouldBeInitialized(cls);
|
||||
}
|
||||
|
||||
private static class EnsureInitialized extends ClassValue<WeakReference<Thread>> {
|
||||
@Override
|
||||
protected WeakReference<Thread> computeValue(Class<?> type) {
|
||||
UNSAFE.ensureClassInitialized(type);
|
||||
if (UNSAFE.shouldBeInitialized(type))
|
||||
// If the previous call didn't block, this can happen.
|
||||
// We are executing inside <clinit>.
|
||||
return new WeakReference<>(Thread.currentThread());
|
||||
return null;
|
||||
}
|
||||
static final EnsureInitialized INSTANCE = new EnsureInitialized();
|
||||
}
|
||||
|
||||
private void ensureInitialized() {
|
||||
if (checkInitialized(member)) {
|
||||
// The coast is clear. Delete the <clinit> barrier.
|
||||
@ -397,24 +381,12 @@ class DirectMethodHandle extends MethodHandle {
|
||||
}
|
||||
private static boolean checkInitialized(MemberName member) {
|
||||
Class<?> defc = member.getDeclaringClass();
|
||||
WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc);
|
||||
if (ref == null) {
|
||||
return true; // the final state
|
||||
}
|
||||
// Somebody may still be running defc.<clinit>.
|
||||
if (ref.refersTo(Thread.currentThread())) {
|
||||
// If anybody is running defc.<clinit>, it is this thread.
|
||||
if (UNSAFE.shouldBeInitialized(defc))
|
||||
// Yes, we are running it; keep the barrier for now.
|
||||
return false;
|
||||
} else {
|
||||
// We are in a random thread. Block.
|
||||
UNSAFE.ensureClassInitialized(defc);
|
||||
}
|
||||
assert(!UNSAFE.shouldBeInitialized(defc));
|
||||
// put it into the final state
|
||||
EnsureInitialized.INSTANCE.remove(defc);
|
||||
return true;
|
||||
UNSAFE.ensureClassInitialized(defc);
|
||||
// Once we get here either defc was fully initialized by another thread, or
|
||||
// defc was already being initialized by the current thread. In the latter case
|
||||
// the barrier must remain. We can detect this simply by checking if initialization
|
||||
// is still needed.
|
||||
return !UNSAFE.shouldBeInitialized(defc);
|
||||
}
|
||||
|
||||
/*non-public*/
|
||||
|
@ -1143,9 +1143,14 @@ public final class Unsafe {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given class has been initialized. This is often
|
||||
* needed in conjunction with obtaining the static field base of a
|
||||
* class.
|
||||
* Ensures the given class has been initialized (see JVMS-5.5 for details).
|
||||
* This is often needed in conjunction with obtaining the static field base
|
||||
* of a class.
|
||||
*
|
||||
* The call returns when either class {@code c} is fully initialized or
|
||||
* class {@code c} is being initialized and the call is performed from
|
||||
* the initializing thread. In the latter case a subsequent call to
|
||||
* {@link #shouldBeInitialized} will return {@code true}.
|
||||
*/
|
||||
public void ensureClassInitialized(Class<?> c) {
|
||||
if (c == null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user