Skip to content

Instantly share code, notes, and snippets.

@headius
Created May 18, 2009 12:19
Show Gist options
  • Save headius/113440 to your computer and use it in GitHub Desktop.
Save headius/113440 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 target = new GuardedRubyMethodHandle(CacheEntry.NULL_CACHE, site);
site.setTarget(target);
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 class GuardedRubyMethodHandle extends JavaMethodHandle {
final CacheEntry entry;
final CallSite site;
public GuardedRubyMethodHandle(CacheEntry entry, CallSite site) {
super(DEFAULT);
this.entry = entry;
this.site = site;
}
public IRubyObject invoke(ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0) {
if (entry.typeOk(self.getMetaClass())) {
return entry.method.call(context, self, self.getMetaClass(), name, arg0);
} else {
CacheEntry newEntry = self.getMetaClass().searchWithCache(name);
site.setTarget(new GuardedRubyMethodHandle(newEntry, site));
return newEntry.method.call(context, self, self.getMetaClass(), name, arg0);
}
}
private static final MethodHandle DEFAULT =
MethodHandles.lookup().findVirtual(GuardedRubyMethodHandle.class, "invoke",
MethodType.make(IRubyObject.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment