headius (owner)

Revisions

  • 6d7d62 headius Thu May 21 20:15:47 -0700 2009
gist: 115901 Download_button fork
public
Public Clone URL: git://gist.github.com/115901.git
Embed All Files: show embed
Java #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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);
    }
}