// Path: src/main/java/org/dynalang/dynalink/MonomorphicCallSite.java
// public class MonomorphicCallSite extends AbstractRelinkableCallSite {
//     /**
//      * Creates a new call site with monomorphic inline caching strategy.
//      * @param descriptor the descriptor for this call site
//      */
//     public MonomorphicCallSite(final CallSiteDescriptor descriptor) {
//         super(descriptor);
//     }
// 
//     @Override
//     public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
//         setTarget(guardedInvocation.compose(relink));
//     }
// 
//     @Override
//     public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
//         relink(guardedInvocation, relink);
//     }
// }
// 
// Path: src/main/java/org/dynalang/dynalink/RelinkableCallSite.java
// public interface RelinkableCallSite {
//     /**
//      * Initializes the relinkable call site by setting a relink-and-invoke method handle. The call site implementation
//      * is supposed to set this method handle as its target.
//      * @param relinkAndInvoke a relink-and-invoke method handle supplied by the {@link DynamicLinker}.
//      */
//     public void initialize(MethodHandle relinkAndInvoke);
// 
//     /**
//      * Returns the descriptor for this call site.
//      *
//      * @return the descriptor for this call site.
//      */
//     public CallSiteDescriptor getDescriptor();
// 
//     /**
//      * This method will be called by the dynamic linker every time the call site is normally relinked. It will be passed
//      * a {@code GuardedInvocation} that the call site should incorporate into its target method handle. When this method
//      * is called, the call site is allowed to keep other non-invalidated invocations around for implementation of
//      * polymorphic inline caches and compose them with this invocation to form its final target.
//      *
//      * @param guardedInvocation the guarded invocation that the call site should incorporate into its target method
//      * handle.
//      * @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
//      * by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
//      * passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
//      * for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
//      * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
//      */
//     public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback);
// 
//     /**
//      * This method will be called by the dynamic linker every time the call site is relinked and the linker wishes the
//      * call site to throw away any prior linkage state. It will be passed a {@code GuardedInvocation} that the call site
//      * should use to build its target method handle. When this method is called, the call site is discouraged from
//      * keeping previous state around, and is supposed to only link the current invocation.
//      *
//      * @param guardedInvocation the guarded invocation that the call site should use to build its target method handle.
//      * @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
//      * by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
//      * passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
//      * for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
//      * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
//      */
//     public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback);
// }


import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.dynalang.dynalink.MonomorphicCallSite;
import org.dynalang.dynalink.RelinkableCallSite;
import org.dynalang.dynalink.linker.CallSiteDescriptor;
        final CallSite cs = new MonomorphicCallSite(lookup, name, callSiteType);
        MethodHandle boundInvoker =
                MethodHandles.insertArguments(INVOKE_DYNAMICALLY, 0, cs);
        MethodHandle collectedArgsInvoker =
                boundInvoker.asCollector(Object.class, callSiteType
                        .parameterCount()
                        - boundInvoker.type().parameterCount() + 1);
        MethodHandle convertedArgsInvoker =
                MethodHandles.convertArguments(collectedArgsInvoker,
                        callSiteType);
        cs.setTarget(convertedArgsInvoker);
        return cs;
    }

    private static MethodHandle INVOKE_DYNAMICALLY;
    static {
        try {
            INVOKE_DYNAMICALLY =
                    MethodHandles.lookup().findStatic(
                            DynamicDispatchDemo.class,
                            "invokeDynamically",
                            MethodType.methodType(Object.class,
                                    RelinkableCallSite.class, Object[].class));
        } catch(IllegalAccessException e) {
            throw new UndeclaredThrowableException(e);
        } catch(NoSuchMethodException e) {
            throw new UndeclaredThrowableException(e);
        }
    }

// Path: src/main/java/org/dynalang/dynalink/MonomorphicCallSite.java
// public class MonomorphicCallSite extends AbstractRelinkableCallSite {
//     /**
//      * Creates a new call site with monomorphic inline caching strategy.
//      * @param descriptor the descriptor for this call site
//      */
//     public MonomorphicCallSite(final CallSiteDescriptor descriptor) {
//         super(descriptor);
//     }
// 
//     @Override
//     public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
//         setTarget(guardedInvocation.compose(relink));
//     }
// 
//     @Override
//     public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
//         relink(guardedInvocation, relink);
//     }
// }
// 
// Path: src/main/java/org/dynalang/dynalink/RelinkableCallSite.java
// public interface RelinkableCallSite {
//     /**
//      * Initializes the relinkable call site by setting a relink-and-invoke method handle. The call site implementation
//      * is supposed to set this method handle as its target.
//      * @param relinkAndInvoke a relink-and-invoke method handle supplied by the {@link DynamicLinker}.
//      */
//     public void initialize(MethodHandle relinkAndInvoke);
// 
//     /**
//      * Returns the descriptor for this call site.
//      *
//      * @return the descriptor for this call site.
//      */
//     public CallSiteDescriptor getDescriptor();
// 
//     /**
//      * This method will be called by the dynamic linker every time the call site is normally relinked. It will be passed
//      * a {@code GuardedInvocation} that the call site should incorporate into its target method handle. When this method
//      * is called, the call site is allowed to keep other non-invalidated invocations around for implementation of
//      * polymorphic inline caches and compose them with this invocation to form its final target.
//      *
//      * @param guardedInvocation the guarded invocation that the call site should incorporate into its target method
//      * handle.
//      * @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
//      * by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
//      * passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
//      * for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
//      * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
//      */
//     public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback);
// 
//     /**
//      * This method will be called by the dynamic linker every time the call site is relinked and the linker wishes the
//      * call site to throw away any prior linkage state. It will be passed a {@code GuardedInvocation} that the call site
//      * should use to build its target method handle. When this method is called, the call site is discouraged from
//      * keeping previous state around, and is supposed to only link the current invocation.
//      *
//      * @param guardedInvocation the guarded invocation that the call site should use to build its target method handle.
//      * @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
//      * by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
//      * passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
//      * for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
//      * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
//      */
//     public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback);
// }


// Path: src/test/java_inactive/DynamicDispatchDemo.java
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.dynalang.dynalink.MonomorphicCallSite;
import org.dynalang.dynalink.RelinkableCallSite;
import org.dynalang.dynalink.linker.CallSiteDescriptor;

        final CallSite cs = new MonomorphicCallSite(lookup, name, callSiteType);
        MethodHandle boundInvoker =
                MethodHandles.insertArguments(INVOKE_DYNAMICALLY, 0, cs);
        MethodHandle collectedArgsInvoker =
                boundInvoker.asCollector(Object.class, callSiteType
                        .parameterCount()
                        - boundInvoker.type().parameterCount() + 1);
        MethodHandle convertedArgsInvoker =
                MethodHandles.convertArguments(collectedArgsInvoker,
                        callSiteType);
        cs.setTarget(convertedArgsInvoker);
        return cs;
    }

    private static MethodHandle INVOKE_DYNAMICALLY;
    static {
        try {
            INVOKE_DYNAMICALLY =
                    MethodHandles.lookup().findStatic(
                            DynamicDispatchDemo.class,
                            "invokeDynamically",
                            MethodType.methodType(Object.class,
                                    RelinkableCallSite.class, Object[].class));
        } catch(IllegalAccessException e) {
            throw new UndeclaredThrowableException(e);
        } catch(NoSuchMethodException e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    private static Object invokeDynamically(RelinkableCallSite callSite,