8234401: ConstantCallSite may stuck in non-frozen state

Reviewed-by: psandoz
This commit is contained in:
Vladimir Ivanov 2019-11-26 16:09:17 +03:00
parent d5c759accb
commit e515a609e9
5 changed files with 94 additions and 24 deletions

View file

@ -87,9 +87,10 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam
abstract
public class CallSite {
// The actual payload of this call site:
// The actual payload of this call site.
// Can be modified using {@link MethodHandleNatives#setCallSiteTargetNormal} or {@link MethodHandleNatives#setCallSiteTargetVolatile}.
/*package-private*/
MethodHandle target; // Note: This field is known to the JVM. Do not change.
final MethodHandle target; // Note: This field is known to the JVM.
/**
* Make a blank call site object with the given method type.
@ -129,11 +130,11 @@ public class CallSite {
*/
/*package-private*/
CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
this(targetType);
this(targetType); // need to initialize target to make CallSite.type() work in createTargetHook
ConstantCallSite selfCCS = (ConstantCallSite) this;
MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS);
checkTargetChange(this.target, boundTarget);
this.target = boundTarget;
setTargetNormal(boundTarget); // ConstantCallSite doesn't publish CallSite.target
UNSAFE.storeStoreFence(); // barrier between target and isFrozen updates
}
/**
@ -190,11 +191,12 @@ public class CallSite {
*/
public abstract void setTarget(MethodHandle newTarget);
void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
MethodType oldType = oldTarget.type();
private void checkTargetChange(MethodHandle newTarget) {
MethodType oldType = target.type(); // target is always present
MethodType newType = newTarget.type(); // null check!
if (!newType.equals(oldType))
if (newType != oldType) {
throw wrongTargetType(newTarget, oldType);
}
}
private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
@ -217,7 +219,7 @@ public class CallSite {
*/
public abstract MethodHandle dynamicInvoker();
/*non-public*/
/*package-private*/
MethodHandle makeDynamicInvoker() {
MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
@ -283,19 +285,24 @@ public class CallSite {
}
/*package-private*/
void setTargetNormal(MethodHandle newTarget) {
final void setTargetNormal(MethodHandle newTarget) {
checkTargetChange(newTarget);
MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
}
/*package-private*/
MethodHandle getTargetVolatile() {
final MethodHandle getTargetVolatile() {
return (MethodHandle) UNSAFE.getReferenceVolatile(this, getTargetOffset());
}
/*package-private*/
void setTargetVolatile(MethodHandle newTarget) {
final void setTargetVolatile(MethodHandle newTarget) {
checkTargetChange(newTarget);
MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
}
// this implements the upcall from the JVM, MethodHandleNatives.linkCallSite:
/*package-private*/
static CallSite makeSite(MethodHandle bootstrapMethod,
// Callee information:
String name, MethodType type,