Skip to content

Instantly share code, notes, and snippets.

@headius
Created May 22, 2009 03:15
Show Gist options
  • Save headius/115901 to your computer and use it in GitHub Desktop.
Save headius/115901 to your computer and use it in GitHub Desktop.
public class InvokeDynamicSupport {
public static CallSite bootstrap(Class caller, String name, MethodType type) {
CallSite site = new CallSite(caller, name, type);
MethodHandle fallback = MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "fallback",
MethodType.make(IRubyObject.class, CallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class));
fallback = MethodHandles.insertArgument(fallback, 0, site);
site.setTarget(fallback);
return site;
}
public static void registerBootstrap(Class cls) {
MethodType bootstrapType = MethodType.make(CallSite.class, Class.class, String.class, MethodType.class);
MethodHandle bootstrap
= MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "bootstrap", bootstrapType);
Linkage.registerBootstrapMethod(cls, bootstrap);
}
public static void installBytecode(MethodVisitor method, String classname) {
SkinnyMethodAdapter mv = new SkinnyMethodAdapter(method);
mv.ldc(c(classname));
mv.invokestatic(p(Class.class), "forName", sig(Class.class, params(String.class)));
mv.invokestatic(p(InvokeDynamicSupport.class), "registerBootstrap", sig(void.class, Class.class));
}
public static boolean test(CacheEntry entry, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0) {
return entry.typeOk(self.getMetaClass());
}
public static IRubyObject target(CacheEntry entry, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0) {
return entry.method.call(context, self, self.getMetaClass(), name, arg0);
}
public static IRubyObject fallback(CallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0) {
CacheEntry newEntry = self.getMetaClass().searchWithCache(name);
MethodHandle test = MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "test",
MethodType.make(boolean.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class));
test = MethodHandles.insertArgument(test, 0, newEntry);
MethodHandle target = MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "target",
MethodType.make(IRubyObject.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class));
target = MethodHandles.insertArgument(target, 0, newEntry);
MethodHandle fallback = MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "fallback",
MethodType.make(IRubyObject.class, CallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class));
fallback = MethodHandles.insertArgument(fallback, 0, site);
site.setTarget(MethodHandles.guardWithTest(test, target, fallback));
return newEntry.method.call(context, self, self.getMetaClass(), name, arg0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment