nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java
changeset 33333 0bad500ce4e0
parent 33007 03119bfefbbf
child 33335 a46c85103868
equal deleted inserted replaced
33332:f180be6368d8 33333:0bad500ce4e0
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    82 */
    82 */
    83 
    83 
    84 package jdk.internal.dynalink.linker;
    84 package jdk.internal.dynalink.linker;
    85 
    85 
    86 import static jdk.nashorn.internal.lookup.Lookup.MH;
       
    87 
       
    88 import java.lang.invoke.MethodHandle;
    86 import java.lang.invoke.MethodHandle;
    89 import java.lang.invoke.MethodHandles;
    87 import java.lang.invoke.MethodHandles;
    90 import java.lang.invoke.MethodType;
    88 import java.lang.invoke.MethodType;
    91 import java.lang.invoke.SwitchPoint;
    89 import java.lang.invoke.SwitchPoint;
    92 import java.lang.invoke.WrongMethodTypeException;
       
    93 import java.util.List;
    90 import java.util.List;
    94 import java.util.Objects;
    91 import java.util.Objects;
    95 import jdk.internal.dynalink.CallSiteDescriptor;
    92 import jdk.internal.dynalink.CallSiteDescriptor;
    96 import jdk.internal.dynalink.support.Guards;
    93 import jdk.internal.dynalink.support.Guards;
    97 
    94 
    98 /**
    95 /**
    99  * Represents a conditionally valid method handle. It is an immutable triple of an invocation method handle, a guard
    96  * Represents a conditionally valid method handle. Usually produced as a return
   100  * method handle that defines the applicability of the invocation handle, and a switch point that can be used for
    97  * value of
   101  * external invalidation of the invocation handle. The invocation handle is suitable for invocation if the guard
    98  * {@link GuardingDynamicLinker#getGuardedInvocation(LinkRequest, LinkerServices)}
   102  * handle returns true for its arguments, and as long as the switch point is not invalidated. Both the guard and the
    99  * and {@link GuardingTypeConverterFactory#convertToType(Class, Class)}. It is
   103  * switch point are optional; neither, one, or both can be present.
   100  * an immutable tuple of an invocation method handle, a guard method handle that
       
   101  * defines the applicability of the invocation handle, zero or more switch
       
   102  * points that can be used for external invalidation of the invocation handle,
       
   103  * and an exception type that if thrown during an invocation of the method
       
   104  * handle also invalidates it. The invocation handle is suitable for invocation
       
   105  * if the guard handle returns true for its arguments, and as long as any of the
       
   106  * switch points are not invalidated, and as long as it does not throw an
       
   107  * exception of the designated type. The guard, the switch point, and the
       
   108  * exception type are all optional (a guarded invocation having none of them is
       
   109  * unconditionally valid).
   104  */
   110  */
   105 public class GuardedInvocation {
   111 public class GuardedInvocation {
   106     private final MethodHandle invocation;
   112     private final MethodHandle invocation;
   107     private final MethodHandle guard;
   113     private final MethodHandle guard;
   108     private final Class<? extends Throwable> exception;
   114     private final Class<? extends Throwable> exception;
   109     private final SwitchPoint[] switchPoints;
   115     private final SwitchPoint[] switchPoints;
   110 
   116 
   111     /**
   117     /**
   112      * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations.
   118      * Creates a new unconditional guarded invocation. It is unconditional as it
   113      *
   119      * has no invalidations.
   114      * @param invocation the method handle representing the invocation. Must not be null.
   120      *
       
   121      * @param invocation the method handle representing the invocation. Must not
       
   122      * be null.
   115      * @throws NullPointerException if invocation is null.
   123      * @throws NullPointerException if invocation is null.
   116      */
   124      */
   117     public GuardedInvocation(final MethodHandle invocation) {
   125     public GuardedInvocation(final MethodHandle invocation) {
   118         this(invocation, null, (SwitchPoint)null, null);
   126         this(invocation, null, (SwitchPoint)null, null);
   119     }
   127     }
   120 
   128 
   121     /**
   129     /**
   122      * Creates a new guarded invocation.
   130      * Creates a new guarded invocation, with a guard method handle.
   123      *
   131      *
   124      * @param invocation the method handle representing the invocation. Must not be null.
   132      * @param invocation the method handle representing the invocation. Must not
   125      * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
   133      * be null.
   126      * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null to represent
   134      * @param guard the method handle representing the guard. Must have be
   127      * an unconditional invocation, although that is unusual.
   135      * compatible with the {@code invocation} handle as per
       
   136      * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}.
       
   137      * For some useful guards, check out the {@link Guards} class. It can be
       
   138      * null to represent an unconditional invocation.
   128      * @throws NullPointerException if invocation is null.
   139      * @throws NullPointerException if invocation is null.
   129      */
   140      */
   130     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) {
   141     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) {
   131         this(invocation, guard, (SwitchPoint)null, null);
   142         this(invocation, guard, (SwitchPoint)null, null);
   132     }
   143     }
   133 
   144 
   134     /**
   145     /**
   135      * Creates a new guarded invocation.
   146      * Creates a new guarded invocation that can be invalidated by a switch
   136      *
   147      * point.
   137      * @param invocation the method handle representing the invocation. Must not be null.
   148      *
   138      * @param switchPoint the optional switch point that can be used to invalidate this linkage.
   149      * @param invocation the method handle representing the invocation. Must
       
   150      * not be null.
       
   151      * @param switchPoint the optional switch point that can be used to
       
   152      * invalidate this linkage. It can be null. If it is null, this represents
       
   153      * an unconditional invocation.
   139      * @throws NullPointerException if invocation is null.
   154      * @throws NullPointerException if invocation is null.
   140      */
   155      */
   141     public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) {
   156     public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) {
   142         this(invocation, null, switchPoint, null);
   157         this(invocation, null, switchPoint, null);
   143     }
   158     }
   144 
   159 
   145     /**
   160     /**
   146      * Creates a new guarded invocation.
   161      * Creates a new guarded invocation, with both a guard method handle and a
   147      *
   162      * switch point that can be used to invalidate it.
   148      * @param invocation the method handle representing the invocation. Must not be null.
   163      *
   149      * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
   164      * @param invocation the method handle representing the invocation. Must
   150      * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
   165      * not be null.
   151      * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
   166      * @param guard the method handle representing the guard. Must have be
   152      * @param switchPoint the optional switch point that can be used to invalidate this linkage.
   167      * compatible with the {@code invocation} handle as per
       
   168      * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}.
       
   169      * For some useful guards, check out the {@link Guards} class. It can be
       
   170      * null. If both it and the switch point are null, this represents an
       
   171      * unconditional invocation.
       
   172      * @param switchPoint the optional switch point that can be used to
       
   173      * invalidate this linkage.
   153      * @throws NullPointerException if invocation is null.
   174      * @throws NullPointerException if invocation is null.
   154      */
   175      */
   155     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) {
   176     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) {
   156         this(invocation, guard, switchPoint, null);
   177         this(invocation, guard, switchPoint, null);
   157     }
   178     }
   158 
   179 
   159     /**
   180     /**
   160      * Creates a new guarded invocation.
   181      * Creates a new guarded invocation, with a guard method handle, a
   161      *
   182      * switch point that can be used to invalidate it, and an exception that if
   162      * @param invocation the method handle representing the invocation. Must not be null.
   183      * thrown when invoked also invalidates it.
   163      * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
   184      *
   164      * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
   185      * @param invocation the method handle representing the invocation. Must not
   165      * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
   186      * be null.
   166      * @param switchPoint the optional switch point that can be used to invalidate this linkage.
   187      * @param guard the method handle representing the guard. Must have be
   167      * @param exception the optional exception type that is expected to be thrown by the invocation and that also
   188      * compatible with the {@code invocation} handle as per
   168      * invalidates the linkage.
   189      * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}.
       
   190      * For some useful guards, check out the {@link Guards} class. It can be
       
   191      * null. If it and the switch point and the exception are all null, this
       
   192      * represents an unconditional invocation.
       
   193      * @param switchPoint the optional switch point that can be used to
       
   194      * invalidate this linkage.
       
   195      * @param exception the optional exception type that is when thrown by the
       
   196      * invocation also invalidates it.
   169      * @throws NullPointerException if invocation is null.
   197      * @throws NullPointerException if invocation is null.
   170      */
   198      */
   171     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) {
   199     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) {
   172         this.invocation = Objects.requireNonNull(invocation);
   200         this.invocation = Objects.requireNonNull(invocation);
   173         this.guard = guard;
   201         this.guard = guard;
   174         this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
   202         this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
   175         this.exception = exception;
   203         this.exception = exception;
   176     }
   204     }
   177 
   205 
   178     /**
   206     /**
   179      * Creates a new guarded invocation
   207      * Creates a new guarded invocation, with a guard method handle, any number
   180      *
   208      * of switch points that can be used to invalidate it, and an exception that
   181      * @param invocation the method handle representing the invocation. Must not be null.
   209      * if thrown when invoked also invalidates it.
   182      * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
   210      *
   183      * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
   211      * @param invocation the method handle representing the invocation. Must not
   184      * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
   212      * be null.
   185      * @param switchPoints the optional switch points that can be used to invalidate this linkage.
   213      * @param guard the method handle representing the guard. Must have be
   186      * @param exception the optional exception type that is expected to be thrown by the invocation and that also
   214      * compatible with the {@code invocation} handle as per
   187      * invalidates the linkage.
   215      * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}.
       
   216      * For some useful guards, check out the {@link Guards} class. It can be
       
   217      * null. If it and the exception are both null, and no switch points were
       
   218      * specified, this represents an unconditional invocation.
       
   219      * @param switchPoints optional switch points that can be used to
       
   220      * invalidate this linkage.
       
   221      * @param exception the optional exception type that is when thrown by the
       
   222      * invocation also invalidates it.
   188      * @throws NullPointerException if invocation is null.
   223      * @throws NullPointerException if invocation is null.
   189      */
   224      */
   190     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
   225     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
   191         this.invocation = Objects.requireNonNull(invocation);
   226         this.invocation = Objects.requireNonNull(invocation);
   192         this.guard = guard;
   227         this.guard = guard;
   211     public MethodHandle getGuard() {
   246     public MethodHandle getGuard() {
   212         return guard;
   247         return guard;
   213     }
   248     }
   214 
   249 
   215     /**
   250     /**
   216      * Returns the switch point that can be used to invalidate the invocation handle.
   251      * Returns the switch points that can be used to invalidate the linkage of
   217      *
   252      * this invocation handle.
   218      * @return the switch point that can be used to invalidate the invocation handle. Can be null.
   253      *
       
   254      * @return the switch points that can be used to invalidate the linkage of
       
   255      * this invocation handle. Can be null.
   219      */
   256      */
   220     public SwitchPoint[] getSwitchPoints() {
   257     public SwitchPoint[] getSwitchPoints() {
   221         return switchPoints == null ? null : switchPoints.clone();
   258         return switchPoints == null ? null : switchPoints.clone();
   222     }
   259     }
   223 
   260 
   224     /**
   261     /**
   225      * Returns the exception type that if thrown should be used to invalidate the linkage.
   262      * Returns the exception type that if thrown by the invocation should
   226      *
   263      * invalidate the linkage of this guarded invocation.
   227      * @return the exception type that if thrown should be used to invalidate the linkage. Can be null.
   264      *
       
   265      * @return the exception type that if thrown should be used to invalidate
       
   266      * the linkage. Can be null.
   228      */
   267      */
   229     public Class<? extends Throwable> getException() {
   268     public Class<? extends Throwable> getException() {
   230         return exception;
   269         return exception;
   231     }
   270     }
   232 
   271 
   233     /**
   272     /**
   234      * Returns true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
   273      * Returns true if and only if this guarded invocation has at least one
   235      * @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
   274      * invalidated switch point.
       
   275      * @return true if and only if this guarded invocation has at least one
       
   276      * invalidated switch point.
   236      */
   277      */
   237     public boolean hasBeenInvalidated() {
   278     public boolean hasBeenInvalidated() {
   238         if (switchPoints == null) {
   279         if (switchPoints == null) {
   239             return false;
   280             return false;
   240         }
   281         }
   245         }
   286         }
   246         return false;
   287         return false;
   247     }
   288     }
   248 
   289 
   249     /**
   290     /**
   250      * Asserts that the invocation is of the specified type, and the guard (if present) is of the specified type with a
       
   251      * boolean return type.
       
   252      *
       
   253      * @param type the asserted type
       
   254      * @throws WrongMethodTypeException if the invocation and the guard are not of the expected method type.
       
   255      */
       
   256     public void assertType(final MethodType type) {
       
   257         assertType(invocation, type);
       
   258         if (guard != null) {
       
   259             assertType(guard, type.changeReturnType(Boolean.TYPE));
       
   260         }
       
   261     }
       
   262 
       
   263     /**
       
   264      * Creates a new guarded invocation with different methods, preserving the switch point.
   291      * Creates a new guarded invocation with different methods, preserving the switch point.
   265      *
   292      *
   266      * @param newInvocation the new invocation
   293      * @param newInvocation the new invocation
   267      * @param newGuard the new guard
   294      * @param newGuard the new guard
   268      * @return a new guarded invocation with the replaced methods and the same switch point as this invocation.
   295      * @return a new guarded invocation with the replaced methods and the same switch point as this invocation.
   270     public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) {
   297     public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) {
   271         return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception);
   298         return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception);
   272     }
   299     }
   273 
   300 
   274     /**
   301     /**
   275      * Add a switchpoint to this guarded invocation
   302      * Create a new guarded invocation with an added switch point.
   276      * @param newSwitchPoint new switchpoint, or null for nop
   303      * @param newSwitchPoint new switch point. Can be null in which case this
   277      * @return new guarded invocation with the extra switchpoint
   304      * method return the current guarded invocation with no changes.
       
   305      * @return a guarded invocation with the added switch point.
   278      */
   306      */
   279     public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
   307     public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
   280         if (newSwitchPoint == null) {
   308         if (newSwitchPoint == null) {
   281             return this;
   309             return this;
   282         }
   310         }
   299         }
   327         }
   300         return replaceMethods(newInvocation, newGuard);
   328         return replaceMethods(newInvocation, newGuard);
   301     }
   329     }
   302 
   330 
   303     /**
   331     /**
   304      * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
   332      * Changes the type of the invocation, as if
   305      * and its guard, if it has one (with return type changed to boolean, and parameter count potentially truncated for
   333      * {@link MethodHandle#asType(MethodType)} was applied to its invocation
   306      * the guard). If the invocation already is of the required type, returns this object.
   334      * and its guard, if it has one (with return type changed to boolean, and
       
   335      * parameter count potentially truncated for the guard). If the invocation
       
   336      * already is of the required type, returns this object.
   307      * @param newType the new type of the invocation.
   337      * @param newType the new type of the invocation.
   308      * @return a guarded invocation with the new type applied to it.
   338      * @return a guarded invocation with the new type applied to it.
   309      */
   339      */
   310     public GuardedInvocation asType(final MethodType newType) {
   340     public GuardedInvocation asType(final MethodType newType) {
   311         return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType));
   341         return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType));
   312     }
   342     }
   313 
   343 
   314     /**
   344     /**
   315      * Changes the type of the invocation, as if {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to
   345      * Changes the type of the invocation, as if
   316      * its invocation and its guard, if it has one (with return type changed to boolean, and parameter count potentially
   346      * {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to
   317      * truncated for the guard). If the invocation already is of the required type, returns this object.
   347      * its invocation and its guard, if it has one (with return type changed to
       
   348      * boolean, and parameter count potentially truncated for the guard). If the
       
   349      * invocation already is of the required type, returns this object.
   318      * @param linkerServices the linker services to use for the conversion
   350      * @param linkerServices the linker services to use for the conversion
   319      * @param newType the new type of the invocation.
   351      * @param newType the new type of the invocation.
   320      * @return a guarded invocation with the new type applied to it.
   352      * @return a guarded invocation with the new type applied to it.
   321      */
   353      */
   322     public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) {
   354     public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) {
   323         return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null :
   355         return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null :
   324             Guards.asType(linkerServices, guard, newType));
   356             Guards.asType(linkerServices, guard, newType));
   325     }
   357     }
   326 
   358 
   327     /**
   359     /**
   328      * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was
   360      * Changes the type of the invocation, as if
   329      * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it
   361      * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was
   330      * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the
   362      * applied to its invocation and
   331      * invocation doesn't change its type, returns this object.
   363      * {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its
       
   364      * guard, if it has one (with return type changed to boolean, and parameter
       
   365      * count potentially truncated for the guard). If the invocation doesn't
       
   366      * change its type, returns this object.
   332      * @param linkerServices the linker services to use for the conversion
   367      * @param linkerServices the linker services to use for the conversion
   333      * @param newType the new type of the invocation.
   368      * @param newType the new type of the invocation.
   334      * @return a guarded invocation with the new type applied to it.
   369      * @return a guarded invocation with the new type applied to it.
   335      */
   370      */
   336     public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) {
   371     public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) {
   337         return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null :
   372         return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null :
   338             Guards.asType(linkerServices, guard, newType));
   373             Guards.asType(linkerServices, guard, newType));
   339     }
   374     }
   340 
   375 
   341     /**
   376     /**
   342      * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
   377      * Changes the type of the invocation, as if
   343      * and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the
   378      * {@link MethodHandle#asType(MethodType)} was applied to its invocation
   344      * required type, returns this object.
   379      * and its guard, if it has one (with return type changed to boolean for
       
   380      * guard). If the invocation already is of the required type, returns this
       
   381      * object.
   345      * @param desc a call descriptor whose method type is adapted.
   382      * @param desc a call descriptor whose method type is adapted.
   346      * @return a guarded invocation with the new type applied to it.
   383      * @return a guarded invocation with the new type applied to it.
   347      */
   384      */
   348     public GuardedInvocation asType(final CallSiteDescriptor desc) {
   385     public GuardedInvocation asType(final CallSiteDescriptor desc) {
   349         return asType(desc.getMethodType());
   386         return asType(desc.getMethodType());
   350     }
   387     }
   351 
   388 
   352     /**
   389     /**
   353      * Applies argument filters to both the invocation and the guard (if there is one).
   390      * Applies argument filters to both the invocation and the guard (if there
       
   391      * is one) with {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}.
   354      * @param pos the position of the first argument being filtered
   392      * @param pos the position of the first argument being filtered
   355      * @param filters the argument filters
   393      * @param filters the argument filters
   356      * @return a filtered invocation
   394      * @return a filtered invocation
   357      */
   395      */
   358     public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
   396     public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
   359         return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
   397         return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
   360             MethodHandles.filterArguments(guard, pos, filters));
   398             MethodHandles.filterArguments(guard, pos, filters));
   361     }
   399     }
   362 
   400 
   363     /**
   401     /**
   364      * Makes an invocation that drops arguments in both the invocation and the guard (if there is one).
   402      * Makes an invocation that drops arguments in both the invocation and the
       
   403      * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, List)}.
   365      * @param pos the position of the first argument being dropped
   404      * @param pos the position of the first argument being dropped
   366      * @param valueTypes the types of the values being dropped
   405      * @param valueTypes the types of the values being dropped
   367      * @return an invocation that drops arguments
   406      * @return an invocation that drops arguments
   368      */
   407      */
   369     public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
   408     public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
   370         return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
   409         return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
   371             MethodHandles.dropArguments(guard, pos, valueTypes));
   410             MethodHandles.dropArguments(guard, pos, valueTypes));
   372     }
   411     }
   373 
   412 
   374     /**
   413     /**
   375      * Makes an invocation that drops arguments in both the invocation and the guard (if there is one).
   414      * Makes an invocation that drops arguments in both the invocation and the
       
   415      * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}.
   376      * @param pos the position of the first argument being dropped
   416      * @param pos the position of the first argument being dropped
   377      * @param valueTypes the types of the values being dropped
   417      * @param valueTypes the types of the values being dropped
   378      * @return an invocation that drops arguments
   418      * @return an invocation that drops arguments
   379      */
   419      */
   380     public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
   420     public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
   382             MethodHandles.dropArguments(guard, pos, valueTypes));
   422             MethodHandles.dropArguments(guard, pos, valueTypes));
   383     }
   423     }
   384 
   424 
   385 
   425 
   386     /**
   426     /**
   387      * Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
   427      * Composes the invocation, guard, switch points, and the exception into a
   388      * @param fallback the fallback method handle in case switchpoint is invalidated or guard returns false.
   428      * composite method handle that knows how to fall back when the guard fails
       
   429      * or the invocation is invalidated.
       
   430      * @param fallback the fallback method handle for when a switch point is
       
   431      * invalidated, a guard returns false, or invalidating exception is thrown.
   389      * @return a composite method handle.
   432      * @return a composite method handle.
   390      */
   433      */
   391     public MethodHandle compose(final MethodHandle fallback) {
   434     public MethodHandle compose(final MethodHandle fallback) {
   392         return compose(fallback, fallback, fallback);
   435         return compose(fallback, fallback, fallback);
   393     }
   436     }
   394 
   437 
   395     /**
   438     /**
   396      * Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
   439      * Composes the invocation, guard, switch points, and the exception into a
   397      * @param switchpointFallback the fallback method handle in case switchpoint is invalidated.
   440      * composite method handle that knows how to fall back when the guard fails
   398      * @param guardFallback the fallback method handle in case guard returns false.
   441      * or the invocation is invalidated.
   399      * @param catchFallback the fallback method in case the exception handler triggers
   442      * @param switchpointFallback the fallback method handle in case a switch
       
   443      * point is invalidated.
       
   444      * @param guardFallback the fallback method handle in case guard returns
       
   445      * false.
       
   446      * @param catchFallback the fallback method in case the exception handler
       
   447      * triggers.
   400      * @return a composite method handle.
   448      * @return a composite method handle.
   401      */
   449      */
   402     public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
   450     public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
   403         final MethodHandle guarded =
   451         final MethodHandle guarded =
   404                 guard == null ?
   452                 guard == null ?
   409                                 guardFallback);
   457                                 guardFallback);
   410 
   458 
   411         final MethodHandle catchGuarded =
   459         final MethodHandle catchGuarded =
   412                 exception == null ?
   460                 exception == null ?
   413                         guarded :
   461                         guarded :
   414                         MH.catchException(
   462                         MethodHandles.catchException(
   415                                 guarded,
   463                                 guarded,
   416                                 exception,
   464                                 exception,
   417                                 MethodHandles.dropArguments(
   465                                 MethodHandles.dropArguments(
   418                                     catchFallback,
   466                                     catchFallback,
   419                                     0,
   467                                     0,
   428             spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
   476             spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
   429         }
   477         }
   430 
   478 
   431         return spGuarded;
   479         return spGuarded;
   432     }
   480     }
   433 
       
   434     private static void assertType(final MethodHandle mh, final MethodType type) {
       
   435         if(!mh.type().equals(type)) {
       
   436             throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());
       
   437         }
       
   438     }
       
   439 }
   481 }