nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java
changeset 33333 0bad500ce4e0
parent 33330 35531ae624ef
equal deleted inserted replaced
33332:f180be6368d8 33333:0bad500ce4e0
    91 import jdk.internal.dynalink.linker.GuardedInvocation;
    91 import jdk.internal.dynalink.linker.GuardedInvocation;
    92 import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
    92 import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
    93 import jdk.internal.dynalink.support.Lookup;
    93 import jdk.internal.dynalink.support.Lookup;
    94 
    94 
    95 /**
    95 /**
    96  * A relinkable call site that maintains a chain of linked method handles. In the default implementation, up to 8 method
    96  * A relinkable call site that implements a polymorphic inline caching strategy.
    97  * handles can be chained, cascading from one to the other through
    97  * It remembers up to 8 {@link GuardedInvocation}s it was linked with, and on
    98  * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. When this call site has to link a new
    98  * each relink request builds a cascading chain of method handles of one
    99  * method handle and the length of the chain is already at the maximum, it will throw away the oldest method handle.
    99  * invocation falling back to the next one. The number of remembered invocations
   100  * Switchpoint-invalidated handles in the chain are removed eagerly (on each linking request, and whenever a
   100  * can be customized by overriding {@link #getMaxChainLength()} in a subclass.
   101  * switchpoint-invalidated method handle is traversed during invocation). There is currently no profiling
   101  * When this call site is relinked with a new invocation and the length of the
   102  * attached to the handles in the chain, so they are never reordered based on usage; the most recently linked method
   102  * chain is already at the maximum, it will throw away the oldest invocation.
   103  * handle is always at the start of the chain.
   103  * Invocations with invalidated switch points and ones for which their
       
   104  * invalidating exception triggered are removed eagerly from the chain. The
       
   105  * invocations are never reordered; the most recently linked method handle is
       
   106  * always at the start of the chain and the least recently linked at its end.
       
   107  * The call site can be safely relinked on more than one thread concurrently.
       
   108  * Race conditions in linking are resolved by throwing away the
       
   109  * {@link GuardedInvocation} produced on the losing thread without incorporating
       
   110  * it into the chain, so it can lead to repeated linking for the same arguments.
   104  */
   111  */
   105 public class ChainedCallSite extends AbstractRelinkableCallSite {
   112 public class ChainedCallSite extends AbstractRelinkableCallSite {
   106     private static final MethodHandle PRUNE_CATCHES;
   113     private static final MethodHandle PRUNE_CATCHES;
   107     private static final MethodHandle PRUNE_SWITCHPOINTS;
   114     private static final MethodHandle PRUNE_SWITCHPOINTS;
   108     static {
   115     static {
   128     public ChainedCallSite(final CallSiteDescriptor descriptor) {
   135     public ChainedCallSite(final CallSiteDescriptor descriptor) {
   129         super(descriptor);
   136         super(descriptor);
   130     }
   137     }
   131 
   138 
   132     /**
   139     /**
   133      * The maximum number of method handles in the chain. Defaults to 8. You can override it in a subclass if you need
   140      * The maximum number of method handles in the chain. Defaults to 8. You can
   134      * to change the value. If your override returns a value less than 1, the code will break.
   141      * override it in a subclass if you need to change the value.
   135      * @return the maximum number of method handles in the chain.
   142      * @return the maximum number of method handles in the chain. The return
       
   143      * value is checked, and if your override returns a value less than 1, a
       
   144      * {@link RuntimeException} will be thrown.
   136      */
   145      */
   137     protected int getMaxChainLength() {
   146     protected int getMaxChainLength() {
   138         return 8;
   147         return 8;
   139     }
   148     }
   140 
   149 
   141     @Override
   150     @Override
   142     public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
   151     public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
   143         relinkInternal(guardedInvocation, fallback, false, false);
   152         relinkInternal(guardedInvocation, relinkAndInvoke, false, false);
   144     }
   153     }
   145 
   154 
   146     @Override
   155     @Override
   147     public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
   156     public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
   148         relinkInternal(guardedInvocation, fallback, true, false);
   157         relinkInternal(guardedInvocation, relinkAndInvoke, true, false);
   149     }
   158     }
   150 
   159 
   151     private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
   160     private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
   152         final Object currentInvocations = invocations;
   161         final Object currentInvocations = invocations;
   153         final LinkedList<GuardedInvocation> newInvocations;
   162         final LinkedList<GuardedInvocation> newInvocations;
   214 
   223 
   215     }
   224     }
   216     /**
   225     /**
   217      * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
   226      * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
   218      * chain.
   227      * chain.
   219      * @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
   228      * @param relinkAndInvoke the ultimate fallback for the chain passed from the dynamic linker.
   220      * @return a method handle for prune-and-invoke
   229      * @return a method handle for prune-and-invoke
   221      */
   230      */
   222     private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) {
   231     private MethodHandle makePruneAndInvokeMethod(final MethodHandle relinkAndInvoke, final MethodHandle prune) {
   223         // Bind prune to (this, relink)
   232         // Bind prune to (this, relink)
   224         final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink);
   233         final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relinkAndInvoke);
   225         // Make it ignore all incoming arguments
   234         // Make it ignore all incoming arguments
   226         final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
   235         final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
   227         // Invoke prune, then invoke the call site target with original arguments
   236         // Invoke prune, then invoke the call site target with original arguments
   228         return MethodHandles.foldArguments(MethodHandles.exactInvoker(type()), ignoreArgsPrune);
   237         return MethodHandles.foldArguments(MethodHandles.exactInvoker(type()), ignoreArgsPrune);
   229     }
   238     }