< prev index next >
src/java.base/share/classes/java/lang/invoke/CallSite.java
Print this page
*** 25,35 ****
package java.lang.invoke;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
- import java.lang.reflect.Field;
import sun.misc.Cleaner;
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* which is called its {@code target}.
--- 25,34 ----
*** 136,184 ****
this.target = boundTarget;
}
/**
* {@code CallSite} dependency context.
! * VM uses context class to store nmethod dependencies on the call site target.
! * Can be in 2 states: (a) null; or (b) {@code Cleaner} instance pointing to some Class instance.
! * Lazily initialized when CallSite instance is linked to some indy call site or VM needs
! * it to store dependencies. As a corollary, "null" context means there are no dependencies
! * registered yet. {@code Cleaner} is used in 2 roles:
! * (a) context class access for VM;
! * (b) stale context class cleanup.
! * {@code Cleaner} holds the context class until cleanup action is finished (see {@code PhantomReference}).
! * Though it's impossible to get the context class using {@code Reference.get()}, VM extracts it directly
! * from {@code Reference.referent} field.
*/
! private volatile Cleaner context = null;
! /**
! * Default context.
! * VM uses it to initialize non-linked CallSite context.
! */
! private static class DefaultContext {}
! private static final Cleaner DEFAULT_CONTEXT = makeContext(DefaultContext.class, null);
!
! private static Cleaner makeContext(Class<?> referent, final CallSite holder) {
! return Cleaner.create(referent,
! new Runnable() {
! @Override public void run() {
! MethodHandleNatives.invalidateDependentNMethods(holder);
}
! });
}
! /** Initialize context class used for nmethod dependency tracking */
! /*package-private*/
! void initContext(Class<?> newContext) {
! // If there are concurrent actions, exactly one succeeds.
! if (context == null) {
! UNSAFE.compareAndSwapObject(this, CONTEXT_OFFSET, /*expected=*/null, makeContext(newContext, this));
! // No need to care about failed CAS attempt.
! // Since initContext is called from indy call site linkage in newContext class, there's no risk
! // that the context class becomes dead while corresponding context cleaner is alive (causing cleanup
! // action in the wrong context).
}
}
/**
* Returns the type of this call site's target.
--- 135,167 ----
this.target = boundTarget;
}
/**
* {@code CallSite} dependency context.
! * JVM uses CallSite.context to store nmethod dependencies on the call site target.
*/
! private final Context context = Context.make(this);
! static class Context implements Runnable {
! static {
! sun.reflect.Reflection.registerFieldsToFilter(Context.class, "dependencies");
}
!
! private final long dependencies = 0; // Used by JVM to store JVM_nmethodBucket*
!
! static Context make(CallSite cs) {
! final Context newContext = new Context();
! // Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context.
! // Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is
! // referenced from Cleaner class) until cleanup is performed.
! Cleaner.create(cs, newContext);
! return newContext;
}
! @Override
! public void run() {
! MethodHandleNatives.clearCallSiteContext(this);
}
}
/**
* Returns the type of this call site's target.
< prev index next >