nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java
changeset 33333 0bad500ce4e0
parent 33330 35531ae624ef
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java	Mon Oct 19 08:39:06 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java	Mon Oct 19 08:45:29 2015 +0200
@@ -93,14 +93,21 @@
 import jdk.internal.dynalink.support.Lookup;
 
 /**
- * A relinkable call site that maintains a chain of linked method handles. In the default implementation, up to 8 method
- * handles can be chained, cascading from one to the other through
- * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. When this call site has to link a new
- * method handle and the length of the chain is already at the maximum, it will throw away the oldest method handle.
- * Switchpoint-invalidated handles in the chain are removed eagerly (on each linking request, and whenever a
- * switchpoint-invalidated method handle is traversed during invocation). There is currently no profiling
- * attached to the handles in the chain, so they are never reordered based on usage; the most recently linked method
- * handle is always at the start of the chain.
+ * A relinkable call site that implements a polymorphic inline caching strategy.
+ * It remembers up to 8 {@link GuardedInvocation}s it was linked with, and on
+ * each relink request builds a cascading chain of method handles of one
+ * invocation falling back to the next one. The number of remembered invocations
+ * can be customized by overriding {@link #getMaxChainLength()} in a subclass.
+ * When this call site is relinked with a new invocation and the length of the
+ * chain is already at the maximum, it will throw away the oldest invocation.
+ * Invocations with invalidated switch points and ones for which their
+ * invalidating exception triggered are removed eagerly from the chain. The
+ * invocations are never reordered; the most recently linked method handle is
+ * always at the start of the chain and the least recently linked at its end.
+ * The call site can be safely relinked on more than one thread concurrently.
+ * Race conditions in linking are resolved by throwing away the
+ * {@link GuardedInvocation} produced on the losing thread without incorporating
+ * it into the chain, so it can lead to repeated linking for the same arguments.
  */
 public class ChainedCallSite extends AbstractRelinkableCallSite {
     private static final MethodHandle PRUNE_CATCHES;
@@ -130,22 +137,24 @@
     }
 
     /**
-     * The maximum number of method handles in the chain. Defaults to 8. You can override it in a subclass if you need
-     * to change the value. If your override returns a value less than 1, the code will break.
-     * @return the maximum number of method handles in the chain.
+     * The maximum number of method handles in the chain. Defaults to 8. You can
+     * override it in a subclass if you need to change the value.
+     * @return the maximum number of method handles in the chain. The return
+     * value is checked, and if your override returns a value less than 1, a
+     * {@link RuntimeException} will be thrown.
      */
     protected int getMaxChainLength() {
         return 8;
     }
 
     @Override
-    public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
-        relinkInternal(guardedInvocation, fallback, false, false);
+    public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
+        relinkInternal(guardedInvocation, relinkAndInvoke, false, false);
     }
 
     @Override
-    public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
-        relinkInternal(guardedInvocation, fallback, true, false);
+    public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
+        relinkInternal(guardedInvocation, relinkAndInvoke, true, false);
     }
 
     private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
@@ -216,12 +225,12 @@
     /**
      * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
      * chain.
-     * @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
+     * @param relinkAndInvoke the ultimate fallback for the chain passed from the dynamic linker.
      * @return a method handle for prune-and-invoke
      */
-    private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) {
+    private MethodHandle makePruneAndInvokeMethod(final MethodHandle relinkAndInvoke, final MethodHandle prune) {
         // Bind prune to (this, relink)
-        final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink);
+        final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relinkAndInvoke);
         // Make it ignore all incoming arguments
         final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
         // Invoke prune, then invoke the call site target with original arguments