Package st.gravel.support.jvm.runtime

Source Code of st.gravel.support.jvm.runtime.BaseCallSite

package st.gravel.support.jvm.runtime;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;

import st.gravel.core.Symbol;
import st.gravel.support.compiler.ast.SelectorConverter;

public abstract class BaseCallSite extends MutableCallSite {

  private static final SelectorConverter selectorConverter = SelectorConverter.factory
      .basicNew();

  protected BaseCallSite(Lookup lookup, MethodType type, String selector) {
    super(type);
    this.selector = selector;
    this.lookup = lookup;
    this.type = type;
    this.fallback = getFallbackMethod();
    reset();
  }

  protected final String selector;
  protected final MethodHandles.Lookup lookup;
  protected final MethodType type;

  public MethodHandle wrapDNUHandle(MethodHandle dnuHandle) {
    Symbol sym = selectorConverter.functionNameAsSelector_(selector);
    MethodHandle withBoundSymbol = MethodHandles.insertArguments(dnuHandle,
        1, sym);
    MethodHandle message = withBoundSymbol.asCollector(Object[].class,
        numArgs());
    return message;
  }

  int numArgs() {
    return type.parameterCount() - 1;
  }

  private static final Set<BaseCallSite> callsites = Collections
      .newSetFromMap(new WeakHashMap<BaseCallSite, Boolean>());

  public synchronized static void register(BaseCallSite callsite) {
    callsites.add(callsite);
  }

  protected final MethodHandle fallback;

  public synchronized static void resetAll() {
    for (BaseCallSite callsite : callsites) {
      callsite.reset();
    }
     MutableCallSite.syncAll(callsites.toArray(new MutableCallSite[callsites.size()]));
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver)
      throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3, Object arg4)
      throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3, arg4);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
      throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3, arg4, arg5);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
      Object arg6) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3, arg4, arg5,
        arg6);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
      Object arg6, Object arg7) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3, arg4, arg5,
        arg6, arg7);
  }

  public static Object invocationFallback(BaseCallSite site, Object receiver,
      Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
      Object arg6, Object arg7, Object arg8) throws Throwable {
    site.addTargetToCache(receiver);
    return site.getTarget().invoke(receiver, arg1, arg2, arg3, arg4, arg5,
        arg6, arg7, arg8);
  }

  private void reset() {
    resetCache();
    setTarget(fallback);
  }

  protected abstract void resetCache();

  private MethodHandle getFallbackMethod() {
    try {
      final MethodType fallbackType = MethodType.genericMethodType(
          type.parameterCount()).insertParameterTypes(0,
          BaseCallSite.class);
      final MethodHandle fallbackHandle = MethodHandles.insertArguments(
          MethodHandles.lookup().findStatic(BaseCallSite.class,
              "invocationFallback", fallbackType), 0, this);
      return fallbackHandle.asType(type);
    } catch (NoSuchMethodException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }

  protected abstract void addTargetToCache(Object receiver);
}
TOP

Related Classes of st.gravel.support.jvm.runtime.BaseCallSite

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.