Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.ir.targets;
  
  import org.jruby.Ruby;
 import  org.objectweb.asm.Handle;
 import  org.objectweb.asm.Opcodes;
 
 
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.methodType;
 import static org.jruby.runtime.invokedynamic.InvokeDynamicSupport.*;
 import static org.jruby.util.CodegenUtils.p;
 import static org.jruby.util.CodegenUtils.sig;
 
 public class Bootstrap {
     public static CallSite string(Lookup lookupString nameMethodType typeString valueint encoding) {
         MethodHandle handle = Binder
                 .from(IRubyObject.classThreadContext.class)
                 .insert(0, new Class[]{String.classint.class}, valueencoding)
                 .invokeStaticQuiet(MethodHandles.lookup(), Bootstrap.class"string");
         CallSite site = new ConstantCallSite(handle);
         return site;
     }
 
     public static CallSite array(Lookup lookupString nameMethodType type) {
         MethodHandle handle = Binder
                 .from(type)
                 .collect(1, IRubyObject[].class)
                 .invokeStaticQuiet(MethodHandles.lookup(), Bootstrap.class"array");
         CallSite site = new ConstantCallSite(handle);
         return site;
     }
 
     private static class InvokeSite extends MutableCallSite {
         public InvokeSite(MethodType typeString name) {
             super(type);
             this. = name;
         }
 
         public final String name;
     }
 
     public static CallSite invoke(Lookup lookupString nameMethodType type) {
         InvokeSite site = new InvokeSite(type, JavaNameMangler.demangleMethodName(name.split(":")[1]));
         MethodHandle handle =
                 insertArguments(
                         findStatic(
                                 lookup,
                                 Bootstrap.class,
                                 "invoke",
                                 type.insertParameterTypes(0, InvokeSite.class)),
                         0,
                         site);
         site.setTarget(handle);
         return site;
     }
 
     public static CallSite attrAssign(Lookup lookupString nameMethodType type) {
         InvokeSite site = new InvokeSite(type, JavaNameMangler.demangleMethodName(name.split(":")[1]));
         MethodHandle handle =
                 insertArguments(
                         findStatic(
                                 lookup,
                                 Bootstrap.class,
                                 "attrAssign",
                                 type.insertParameterTypes(0, InvokeSite.class)),
                         0,
                         site);
        site.setTarget(handle);
        return site;
    }
    public static CallSite invokeSelf(Lookup lookupString nameMethodType type) {
        InvokeSite site = new InvokeSite(type, JavaNameMangler.demangleMethodName(name.split(":")[1]));
        MethodHandle handle =
                insertArguments(
                        findStatic(
                                lookup,
                                Bootstrap.class,
                                "invokeSelf",
                                type.insertParameterTypes(0, InvokeSite.class)),
                        0,
                        site);
        site.setTarget(handle);
        return site;
    }
    public static CallSite ivar(Lookup lookupString nameMethodType typethrows Throwable {
        String[] names = name.split(":");
        String operation = names[0];
        String varName = names[1];
        VariableSite site = new VariableSite(typevarName"noname", 0);
        MethodHandle handle;
        handle = lookup.findStatic(Bootstrap.classoperationtype.insertParameterTypes(0, VariableSite.class));
        handle = handle.bindTo(site);
        site.setTarget(handle.asType(site.type()));
        return site;
    }
    public static CallSite searchConst(Lookup lookupString nameMethodType type) {
        MutableCallSite site = new MutableCallSite(type);
        String[] bits = name.split(":");
        String constName = bits[1];
        MethodHandle handle = Binder
                .from(type)
                .insert(0, siteconstName)
                .invokeStaticQuiet(MethodHandles.lookup(), Bootstrap.class"searchConst");
        site.setTarget(handle);
        return site;
    }
    public static CallSite inheritanceSearchConst(Lookup lookupString nameMethodType type) {
        MutableCallSite site = new MutableCallSite(type);
        String[] bits = name.split(":");
        String constName = bits[1];
        MethodHandle handle = Binder
                .from(type)
                .insert(0, siteconstName)
                .invokeStaticQuiet(MethodHandles.lookup(), Bootstrap.class"inheritanceSearchConst");
        site.setTarget(handle);
        return site;
    }
    public static Handle string() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "string"sig(CallSite.classLookup.classString.classMethodType.classString.classint.class));
    }
    public static Handle array() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "array"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle invoke() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "invoke"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle invokeSelf() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "invokeSelf"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle invokeFixnumOp() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(MathLinker.class), "fixnumOperatorBootstrap"sig(CallSite.classLookup.classString.classMethodType.classlong.classString.classint.class));
    }
    public static Handle attrAssign() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "attrAssign"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle ivar() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "ivar"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle searchConst() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "searchConst"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static Handle inheritanceSearchConst() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "inheritanceSearchConst"sig(CallSite.classLookup.classString.classMethodType.class));
    }
    public static IRubyObject string(String valueint encodingThreadContext context) {
        // obviously wrong: not caching bytelist, not using encoding
        return RubyString.newStringNoCopy(context.runtimevalue.getBytes(.));
    }
    public static IRubyObject array(ThreadContext contextIRubyObject[] elts) {
        return RubyArray.newArrayNoCopy(context.runtimeelts);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfthrows Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 0, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextself);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 1, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 2, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 3, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1arg2);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfthrows Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 0, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextself);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfBlock blockthrows Throwable {
        // TODO: literal block handling of break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 0, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfblock);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0Block blockthrows Throwable {
        // TODO: literal block handling of break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 1, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0block);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1Block blockthrows Throwable {
        // TODO: literal block handling of break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 2, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1block);
    }
    public static IRubyObject invoke(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2Block blockthrows Throwable {
        // TODO: literal block handling of break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 3, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1arg2block);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfBlock blockthrows Throwable {
        // TODO: literal block handling of break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodName);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 0, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfblock);
    }
    public static IRubyObject attrAssign(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 1, false);
        mh = foldArguments(
                mh,
                Binder.from(site.type())
                        .drop(0, 2)
                        .identity());
        site.setTarget(mh);
        mh.invokeWithArguments(contextselfarg0);
        return arg0;
    }
    private static final int[][] PERMUTES = new int[][] {
            new int[]{1, 0},
            new int[]{1, 0, 2},
            new int[]{1, 0, 2, 3},
            new int[]{1, 0, 2, 3, 4},
    };
    private static MethodHandle getHandle(RubyClass selfClassSwitchPoint switchPointInvokeSite siteDynamicMethod methodint arityboolean blockthrows Throwable {
        MethodHandle mh = null;
        if (method.getNativeCall() != null) {
            DynamicMethod.NativeCall nc = method.getNativeCall();
            if (method.getArity().isFixed()) {
                if (method.getArity().getValue() <= 3) {
                    Binder b = Binder.from(site.type());
                    if (!nc.hasContext()) {
                        b.drop(0);
                    }
                    if (nc.hasBlock() && !block) {
                        b.insert(site.type().parameterCount() - 1, .);
                    } else if (!nc.hasBlock() && block) {
                        b.drop(site.type().parameterCount() - 2, 1);
                    }
                    if (nc.isStatic()) {
                        if (b.type().parameterCount() == nc.getNativeSignature().length) {
                            mh = b
                                    .cast(nc.getNativeReturn(), nc.getNativeSignature())
                                    .invokeStaticQuiet(MethodHandles.lookup(), nc.getNativeTarget(), nc.getNativeName());
//                            System.out.println(mh);
                        }
                    } else {
//                        System.out.println(b.type());
//                        System.out.println(Arrays.toString(nc.getNativeSignature()));
                        if (b.type().parameterCount() == nc.getNativeSignature().length + 1) {
                            // only threadcontext-receivers right now
                            mh = b
                                    .permute([arity])
                                    .cast(MethodType.methodType(nc.getNativeReturn(), nc.getNativeTarget(), nc.getNativeSignature()))
                                    .invokeVirtualQuiet(MethodHandles.lookup(), nc.getNativeName());
//                            System.out.println(mh);
                        }
                    }
                }
            }
//            if (mh != null) System.out.println("binding to native: " + site.name);
        }
        if (mh == null) {
            // attempt IR direct binding
            if (method instanceof CompiledIRMethod) {
                mh = (MethodHandle)((CompiledIRMethod)method).getHandle();
                if (!block) {
                    mh = MethodHandles.insertArguments(mhmh.type().parameterCount() - 1, .);
                }
                mh = MethodHandles.insertArguments(mh, 1, ((CompiledIRMethod)method).getStaticScope());
//                System.out.println("binding IR compiled direct: " + site.name);
            }
        }
//        System.out.println(site.name);
//        System.out.println("before: " + mh);
        if (mh == null) {
//            System.out.println(site.type());
            // use DynamicMethod binding
            MethodType type2 = site.type()
                    .insertParameterTypes(2, RubyModule.classString.class)
                    .insertParameterTypes(0, DynamicMethod.class);
            mh = Binder.from(site.type())
                    .insert(2, selfClasssite.name)
//                    .printType()
                    .insert(0, method)
//                    .printType()
                    .cast(type2)
                    .invokeVirtual(MethodHandles.lookup(), "call");
//            System.out.println("binding to DynamicMethod: " + mh);
//            System.out.println("binding to DynamicMethod.call: " + site.name);
        }
        MethodHandle fallback = Binder
                .from(site.type())
                .insert(0, site.name)
//                .printType()
                .invokeStatic(MethodHandles.lookup(), Bootstrap.class"invokeSelfSimple");
//        System.out.println("simple fallback: " + fallback);
        if (mh == null) {
            return fallback;
        } else {
            MethodHandle test = Binder
                    .from(site.type().changeReturnType(boolean.class))
                    .insert(0, new Class[]{RubyClass.class}, selfClass)
                    .invokeStatic(MethodHandles.lookup(), Bootstrap.class"testType");
            mh = MethodHandles.guardWithTest(testmhfallback);
            mh = switchPoint.guardWithTest(mhfallback);
        }
        return mh;
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject self) {
        return self.getMetaClass().invoke(contextselfname.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 1, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0) {
        return self.getMetaClass().invoke(contextselfnamearg0.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0arg1);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 2, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1) {
        return self.getMetaClass().invoke(contextselfnamearg0arg1.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2throws Throwable {
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0arg1arg2);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 3, false);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1arg2);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2) {
        return self.getMetaClass().invoke(contextselfnamearg0arg1arg2.);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfBlock blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        return self.getMetaClass().invoke(contextselfname.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 1, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0block);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        return self.getMetaClass().invoke(contextselfnamearg0.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0arg1);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 2, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1block);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        return self.getMetaClass().invoke(contextselfnamearg0arg1.);
    }
    public static IRubyObject invokeSelf(InvokeSite siteThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        RubyClass selfClass = self.getMetaClass();
        String methodName = site.name;
        SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData();
        CacheEntry entry = selfClass.searchWithCache(methodName);
        DynamicMethod method = entry.method;
        if (methodMissing(entry.methodNameself)) {
            return callMethodMissing(entry.contextselfmethodNamearg0arg1arg2);
        }
        MethodHandle mh = getHandle(selfClassswitchPointsitemethod, 3, true);
        site.setTarget(mh);
        return (IRubyObject)mh.invokeWithArguments(contextselfarg0arg1arg2block);
    }
    public static IRubyObject invokeSelfSimple(String nameThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2Block blockthrows Throwable {
        // TODO: literal block wrapper for break, etc
        return self.getMetaClass().invoke(contextselfnamearg0arg1arg2.);
    }
    public static IRubyObject ivarGet(VariableSite siteIRubyObject selfthrows Throwable {
        RubyClass.VariableAccessor accessor = self.getMetaClass().getRealClass().getVariableAccessorForRead(site.name);
        // produce nil if the variable has not been initialize
        MethodHandle nullToNil = findStatic(RuntimeHelpers.class"nullToNil"methodType(IRubyObject.classIRubyObject.classIRubyObject.class));
        nullToNil = insertArguments(nullToNil, 1, self.getRuntime().getNil());
        nullToNil = explicitCastArguments(nullToNilmethodType(IRubyObject.classObject.class));
        // get variable value and filter with nullToNil
        MethodHandle getValue = findVirtual(IRubyObject.class"getVariable"methodType(Object.classint.class));
        getValue = insertArguments(getValue, 1, accessor.getIndex());
        getValue = filterReturnValue(getValuenullToNil);
        // prepare fallback
        MethodHandle fallback = null;
        if (site.getTarget() == null || site.chainCount() > .) {
//            if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tget triggered site rebind " + self.getMetaClass().id);
            fallback = findStatic(InvokeDynamicSupport.class"getVariableFallback"methodType(IRubyObject.classVariableSite.classIRubyObject.class));
            fallback = fallback.bindTo(site);
            site.clearChainCount();
        } else {
//            if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tget added to PIC " + self.getMetaClass().id);
            fallback = site.getTarget();
            site.incrementChainCount();
        }
        // prepare test
        MethodHandle test = findStatic(InvocationLinker.class"testRealClass"methodType(boolean.classint.classIRubyObject.class));
        test = insertArguments(test, 0, accessor.getClassId());
        getValue = guardWithTest(testgetValuefallback);
//        if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tget on class " + self.getMetaClass().id + " bound directly");
        site.setTarget(getValue);
        return (IRubyObject)getValue.invokeWithArguments(self);
    }
    public static void ivarSet(VariableSite siteIRubyObject selfIRubyObject valuethrows Throwable {
        RubyClass.VariableAccessor accessor = self.getMetaClass().getRealClass().getVariableAccessorForWrite(site.name);
        // set variable value and fold by returning value
        MethodHandle setValue = findVirtual(IRubyObject.class"setVariable"methodType(void.classint.classObject.class));
        setValue = explicitCastArguments(setValuemethodType(void.classIRubyObject.classint.classIRubyObject.class));
        setValue = insertArguments(setValue, 1, accessor.getIndex());
        // prepare fallback
        MethodHandle fallback = null;
        if (site.getTarget() == null || site.chainCount() > .) {
//            if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset triggered site rebind " + self.getMetaClass().id);
            fallback = findStatic(InvokeDynamicSupport.class"setVariableFallback"methodType(void.classVariableSite.classIRubyObject.classIRubyObject.class));
            fallback = fallback.bindTo(site);
            site.clearChainCount();
        } else {
//            if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset added to PIC " + self.getMetaClass().id);
            fallback = site.getTarget();
            site.incrementChainCount();
        }
        // prepare test
        MethodHandle test = findStatic(InvocationLinker.class"testRealClass"methodType(boolean.classint.classIRubyObject.class));
        test = insertArguments(test, 0, accessor.getClassId());
        test = dropArguments(test, 1, IRubyObject.class);
        setValue = guardWithTest(testsetValuefallback);
//        if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset on class " + self.getMetaClass().id + " bound directly");
        site.setTarget(setValue);
        setValue.invokeWithArguments(selfvalue);
    }
    private static MethodHandle findStatic(Class targetString nameMethodType type) {
        return findStatic(lookup(), targetnametype);
    }
    private static MethodHandle findStatic(Lookup lookupClass targetString nameMethodType type) {
        try {
            return lookup.findStatic(targetnametype);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static boolean testType(RubyClass originalThreadContext contextIRubyObject self) {
        // naive test
        return ((RubyBasicObject)self).getMetaClass() == original;
    }
    public static boolean testType(RubyClass originalThreadContext contextIRubyObject selfIRubyObject arg0) {
        // naive test
        return ((RubyBasicObject)self).getMetaClass() == original;
    }
    public static boolean testType(RubyClass originalThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1) {
        // naive test
        return ((RubyBasicObject)self).getMetaClass() == original;
    }
    public static boolean testType(RubyClass originalThreadContext contextIRubyObject selfIRubyObject arg0IRubyObject arg1IRubyObject arg2) {
        // naive test
        return ((RubyBasicObject)self).getMetaClass() == original;
    }
    public static boolean testType(RubyClass originalThreadContext contextIRubyObject selfIRubyObject[] args) {
        // naive test
        return ((RubyBasicObject)self).getMetaClass() == original;
    }
    ///////////////////////////////////////////////////////////////////////////
    // constant lookup
    public static IRubyObject searchConst(MutableCallSite siteString constNameThreadContext contextStaticScope staticScopethrows Throwable {
        Ruby runtime = context.runtime;
        SwitchPoint switchPoint = (SwitchPoint)runtime.getConstantInvalidator().getData();
        IRubyObject value = staticScope.getConstant(runtimeconstNameruntime.getObject());
        if (value == null) {
            return staticScope.getModule().callMethod(context"const_missing"runtime.fastNewSymbol(constName));
        }
        // bind constant until invalidated
        MethodHandle target = Binder.from(site.type())
                .drop(0, 2)
                .constant(value);
        MethodHandle fallback = Binder.from(site.type())
                .insert(0, siteconstName)
                .invokeStatic(MethodHandles.lookup(), Bootstrap.class"searchConst");
        site.setTarget(switchPoint.guardWithTest(targetfallback));
        return value;
    }
    public static IRubyObject inheritanceSearchConst(MutableCallSite siteString constNameThreadContext contextIRubyObject cmValthrows Throwable {
        Ruby runtime = context.runtime;
        RubyModule module;
        if (cmVal instanceof RubyModule) {
            module = (RubyModulecmVal;
        } else {
            throw runtime.newTypeError(cmVal + " is not a type/class");
        }
        SwitchPoint switchPoint = (SwitchPoint)runtime.getConstantInvalidator().getData();
        IRubyObject value = module.getConstantFromNoConstMissing(constNamefalse);
        if (value == null) {
            return (IRubyObject).;
        }
        // bind constant until invalidated
        MethodHandle target = Binder.from(site.type())
                .drop(0, 2)
                .constant(value);
        MethodHandle fallback = Binder.from(site.type())
                .insert(0, siteconstName)
                .invokeStatic(MethodHandles.lookup(), Bootstrap.class"inheritanceSearchConst");
        site.setTarget(switchPoint.guardWithTest(targetfallback));
        return value;
    }
    ///////////////////////////////////////////////////////////////////////////
    // COMPLETED WORK BELOW
    ///////////////////////////////////////////////////////////////////////////
    // Symbol binding
    public static Handle symbol() {
        return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "symbol"sig(CallSite.classLookup.classString.classMethodType.classString.class));
    }
    public static CallSite symbol(Lookup lookupString nameMethodType typeString sym) {
        MutableCallSite site = new MutableCallSite(type);
        MethodHandle handle = Binder
                .from(IRubyObject.classThreadContext.class)
                .insert(0, sitesym)
                .invokeStaticQuiet(MethodHandles.lookup(), Bootstrap.class"symbol");
        site.setTarget(handle);
        return site;
    }
    public static IRubyObject symbol(MutableCallSite siteString nameThreadContext context) {
        RubySymbol symbol = RubySymbol.newSymbol(context.runtimename);
        site.setTarget(Binder
                .from(IRubyObject.classThreadContext.class)
                .drop(0)
                .constant(symbol)
        );
        return symbol;
    }