headius (owner)

Revisions

  • d6e2f4 headius Mon May 18 05:19:24 -0700 2009
gist: 113440 Download_button fork
public
Public Clone URL: git://gist.github.com/113440.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
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));
    }
}