private static MethodHandle dropNameAndArgs( MethodHandle original, int index, int count, boolean block) { switch (count) { case -1: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject[].class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class, IRubyObject[].class); } case 0: if (block) { return MethodHandles.dropArguments(original, index, String.class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class); } case 1: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class, IRubyObject.class); } case 2: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class); } case 3: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class); } default: throw new RuntimeException( "Invalid arg count (" + count + ") while preparing method handle:\n\t" + original); } }
static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class), new int[] {0, 3, 5, 1, 6, 7, 8, 9}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_3); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_3); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args TARGET_3 = target; }
private static MethodHandle createGWT( MethodHandle test, MethodHandle target, MethodHandle fallback, CacheEntry entry, CallSite site) { MethodHandle myTest = MethodHandles.insertArguments(test, 0, entry); MethodHandle myTarget = MethodHandles.insertArguments(target, 0, entry); MethodHandle myFallback = MethodHandles.insertArguments(fallback, 0, site); MethodHandle guardWithTest = MethodHandles.guardWithTest(myTest, myTarget, myFallback); return MethodHandles.convertArguments(guardWithTest, site.type()); }
static { MethodHandle getMethod = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "getMethod", MethodType.make(DynamicMethod.class, CacheEntry.class)); getMethod = MethodHandles.dropArguments(getMethod, 0, RubyClass.class); getMethod = MethodHandles.dropArguments( getMethod, 2, ThreadContext.class, IRubyObject.class, IRubyObject.class); GETMETHOD = getMethod; }
public static CallSite bootstrap(Class caller, String name, MethodType type) { JRubyCallSite site; if (name == "call") { site = new JRubyCallSite(caller, name, type, CallType.NORMAL); } else { site = new JRubyCallSite(caller, name, type, CallType.FUNCTIONAL); } MethodType fallbackType = type.insertParameterType(0, JRubyCallSite.class); MethodHandle myFallback = MethodHandles.insertArguments( MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "fallback", fallbackType), 0, site); site.setTarget(myFallback); return site; }
static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, Block.class), new int[] {0, 3, 5, 1, 6, 7, 8, 9}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_2_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_2_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, 2, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, 2, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_2_B = target; }
static { MethodHandle retryJump = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "retryJumpError", MethodType.make(IRubyObject.class, ThreadContext.class)); // ThreadContext retryJump = MethodHandles.permuteArguments( retryJump, MethodType.make( IRubyObject.class, JumpException.RetryJump.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {2}); // RetryJump, CacheEntry, ThreadContext, IRubyObject, IRubyObject RETRYJUMP = retryJump; }
static { MethodHandle breakJump = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "handleBreakJump", MethodType.make( IRubyObject.class, JumpException.BreakJump.class, ThreadContext.class)); // BreakJump, ThreadContext breakJump = MethodHandles.permuteArguments( breakJump, MethodType.make( IRubyObject.class, JumpException.BreakJump.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {0, 2}); // BreakJump, CacheEntry, ThreadContext, IRubyObject, IRubyObject BREAKJUMP = breakJump; }
public class InvokeDynamicSupport { public static class JRubyCallSite extends CallSite { private final CallType callType; public JRubyCallSite(Class caller, String name, MethodType type, CallType callType) { super(caller, name, type); this.callType = callType; } public CallType callType() { return callType; } } public static CallSite bootstrap(Class caller, String name, MethodType type) { JRubyCallSite site; if (name == "call") { site = new JRubyCallSite(caller, name, type, CallType.NORMAL); } else { site = new JRubyCallSite(caller, name, type, CallType.FUNCTIONAL); } MethodType fallbackType = type.insertParameterType(0, JRubyCallSite.class); MethodHandle myFallback = MethodHandles.insertArguments( MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "fallback", fallbackType), 0, site); site.setTarget(myFallback); return site; } public static void registerBootstrap(Class cls) { 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)); } private static MethodHandle createGWT( MethodHandle test, MethodHandle target, MethodHandle fallback, CacheEntry entry, CallSite site) { MethodHandle myTest = MethodHandles.insertArguments(test, 0, entry); MethodHandle myTarget = MethodHandles.insertArguments(target, 0, entry); MethodHandle myFallback = MethodHandles.insertArguments(fallback, 0, site); MethodHandle guardWithTest = MethodHandles.guardWithTest(myTest, myTarget, myFallback); return MethodHandles.convertArguments(guardWithTest, site.type()); } public static boolean test(CacheEntry entry, IRubyObject self) { return entry.typeOk(self.getMetaClass()); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name); } site.setTarget(createGWT(TEST_0, TARGET_0, FALLBACK_0, entry, site)); return entry.method.call(context, self, selfClass, name); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0); } site.setTarget(createGWT(TEST_1, TARGET_1, FALLBACK_1, entry, site)); return entry.method.call(context, self, selfClass, name, arg0); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0, arg1); } site.setTarget(createGWT(TEST_2, TARGET_2, FALLBACK_2, entry, site)); return entry.method.call(context, self, selfClass, name, arg0, arg1); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0, arg1, arg2); } site.setTarget(createGWT(TEST_3, TARGET_3, FALLBACK_3, entry, site)); return entry.method.call(context, self, selfClass, name, arg0, arg1, arg2); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject[] args) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, args); } site.setTarget(createGWT(TEST_N, TARGET_N, FALLBACK_N, entry, site)); return entry.method.call(context, self, selfClass, name, args); } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, Block block) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); try { if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, block); } site.setTarget(createGWT(TEST_0_B, TARGET_0_B, FALLBACK_0_B, entry, site)); return entry.method.call(context, self, selfClass, name, block); } catch (JumpException.BreakJump bj) { return handleBreakJump(context, bj); } catch (JumpException.RetryJump rj) { return retryJumpError(context); } finally { block.escape(); } } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0, Block block) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); try { if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0, block); } site.setTarget(createGWT(TEST_1_B, TARGET_1_B, FALLBACK_1_B, entry, site)); return entry.method.call(context, self, selfClass, name, arg0, block); } catch (JumpException.BreakJump bj) { return handleBreakJump(context, bj); } catch (JumpException.RetryJump rj) { return retryJumpError(context); } finally { block.escape(); } } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, Block block) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); try { if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0, arg1, block); } site.setTarget(createGWT(TEST_2_B, TARGET_2_B, FALLBACK_2_B, entry, site)); return entry.method.call(context, self, selfClass, name, arg0, arg1, block); } catch (JumpException.BreakJump bj) { return handleBreakJump(context, bj); } catch (JumpException.RetryJump rj) { return retryJumpError(context); } finally { block.escape(); } } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); try { if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing( entry, site.callType(), context, self, name, arg0, arg1, arg2, block); } site.setTarget(createGWT(TEST_3_B, TARGET_3_B, FALLBACK_3_B, entry, site)); return entry.method.call(context, self, selfClass, name, arg0, arg1, arg2, block); } catch (JumpException.BreakJump bj) { return handleBreakJump(context, bj); } catch (JumpException.RetryJump rj) { return retryJumpError(context); } finally { block.escape(); } } public static IRubyObject fallback( JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name, IRubyObject[] args, Block block) { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); try { if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, args, block); } site.setTarget(createGWT(TEST_N_B, TARGET_N_B, FALLBACK_N_B, entry, site)); return entry.method.call(context, self, selfClass, name, args, block); } catch (JumpException.BreakJump bj) { return handleBreakJump(context, bj); } catch (JumpException.RetryJump rj) { return retryJumpError(context); } finally { block.escape(); } } protected static boolean methodMissing( CacheEntry entry, CallType callType, String name, IRubyObject caller) { DynamicMethod method = entry.method; return method.isUndefined() || (callType == CallType.NORMAL && !name.equals("method_missing") && !method.isCallableFrom(caller, callType)); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject[] args) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, args, Block.NULL_BLOCK); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, Block.NULL_BLOCK); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, Block block) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, block); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg, Block.NULL_BLOCK); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject[] args, Block block) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, args, block); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg0, Block block) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg0, block); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg0, arg1, Block.NULL_BLOCK); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, Block block) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg0, arg1, block); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg0, arg1, arg2, Block.NULL_BLOCK); } private static IRubyObject callMethodMissing( CacheEntry entry, CallType callType, ThreadContext context, IRubyObject self, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) { return RuntimeHelpers.selectMethodMissing( context, self, entry.method.getVisibility(), name, callType) .call(context, self, self.getMetaClass(), name, arg0, arg1, arg2, block); } public static RubyClass pollAndGetClass(ThreadContext context, IRubyObject self) { context.callThreadPoll(); RubyClass selfType = self.getMetaClass(); return selfType; } public static IRubyObject handleBreakJump(JumpException.BreakJump bj, ThreadContext context) throws JumpException.BreakJump { if (context.getFrameJumpTarget() == bj.getTarget()) { return (IRubyObject) bj.getValue(); } throw bj; } private static IRubyObject handleBreakJump(ThreadContext context, JumpException.BreakJump bj) throws JumpException.BreakJump { if (context.getFrameJumpTarget() == bj.getTarget()) { return (IRubyObject) bj.getValue(); } throw bj; } public static IRubyObject retryJumpError(ThreadContext context) { throw context .getRuntime() .newLocalJumpError( RubyLocalJumpError.Reason.RETRY, context.getRuntime().getNil(), "retry outside of rescue not supported"); } private static final MethodType BOOTSTRAP_TYPE = MethodType.make(CallSite.class, Class.class, String.class, MethodType.class); private static final MethodHandle BOOTSTRAP = MethodHandles.lookup().findStatic(InvokeDynamicSupport.class, "bootstrap", BOOTSTRAP_TYPE); private static final MethodHandle GETMETHOD; static { MethodHandle getMethod = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "getMethod", MethodType.make(DynamicMethod.class, CacheEntry.class)); getMethod = MethodHandles.dropArguments(getMethod, 0, RubyClass.class); getMethod = MethodHandles.dropArguments( getMethod, 2, ThreadContext.class, IRubyObject.class, IRubyObject.class); GETMETHOD = getMethod; } public static final DynamicMethod getMethod(CacheEntry entry) { return entry.method; } private static final MethodHandle PGC = MethodHandles.dropArguments( MethodHandles.dropArguments( MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "pollAndGetClass", MethodType.make(RubyClass.class, ThreadContext.class, IRubyObject.class)), 1, IRubyObject.class), 0, CacheEntry.class); private static final MethodHandle TEST = MethodHandles.dropArguments( MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "test", MethodType.make(boolean.class, CacheEntry.class, IRubyObject.class)), 1, ThreadContext.class, IRubyObject.class); private static MethodHandle dropNameAndArgs( MethodHandle original, int index, int count, boolean block) { switch (count) { case -1: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject[].class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class, IRubyObject[].class); } case 0: if (block) { return MethodHandles.dropArguments(original, index, String.class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class); } case 1: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments(original, index, String.class, IRubyObject.class); } case 2: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class); } case 3: if (block) { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class); } else { return MethodHandles.dropArguments( original, index, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class); } default: throw new RuntimeException( "Invalid arg count (" + count + ") while preparing method handle:\n\t" + original); } } private static final MethodHandle PGC_0 = dropNameAndArgs(PGC, 4, 0, false); private static final MethodHandle GETMETHOD_0 = dropNameAndArgs(GETMETHOD, 5, 0, false); private static final MethodHandle TEST_0 = dropNameAndArgs(TEST, 4, 0, false); private static final MethodHandle TARGET_0; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class), new int[] {0, 3, 5, 1, 6}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String target = MethodHandles.foldArguments(target, GETMETHOD_0); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String target = MethodHandles.foldArguments(target, PGC_0); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String TARGET_0 = target; } private static final MethodHandle FALLBACK_0 = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class)); private static final MethodHandle PGC_1 = dropNameAndArgs(PGC, 4, 1, false); private static final MethodHandle GETMETHOD_1 = dropNameAndArgs(GETMETHOD, 5, 1, false); private static final MethodHandle TEST_1 = dropNameAndArgs(TEST, 4, 1, false); private static final MethodHandle TARGET_1; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class)); // IRubyObject, DynamicMethod, ThreadContext, IRubyObject, RubyModule, String, IRubyObject target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class)); // IRubyObject, DynamicMethod, ThreadContext, IRubyObject, RubyClass, String, IRubyObject target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class), new int[] {0, 3, 5, 1, 6, 7}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, IRubyObject target = MethodHandles.foldArguments(target, GETMETHOD_1); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, // IRubyObject target = MethodHandles.foldArguments(target, PGC_1); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, IRubyObject TARGET_1 = target; } private static final MethodHandle FALLBACK_1 = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class)); private static final MethodHandle PGC_2 = dropNameAndArgs(PGC, 4, 2, false); private static final MethodHandle GETMETHOD_2 = dropNameAndArgs(GETMETHOD, 5, 2, false); private static final MethodHandle TEST_2 = dropNameAndArgs(TEST, 4, 2, false); private static final MethodHandle TARGET_2; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class), new int[] {0, 3, 5, 1, 6, 7, 8}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_2); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_2); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args TARGET_2 = target; } private static final MethodHandle FALLBACK_2 = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class)); private static final MethodHandle PGC_3 = dropNameAndArgs(PGC, 4, 3, false); private static final MethodHandle GETMETHOD_3 = dropNameAndArgs(GETMETHOD, 5, 3, false); private static final MethodHandle TEST_3 = dropNameAndArgs(TEST, 4, 3, false); private static final MethodHandle TARGET_3; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class), new int[] {0, 3, 5, 1, 6, 7, 8, 9}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_3); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_3); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args TARGET_3 = target; } private static final MethodHandle FALLBACK_3 = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class)); private static final MethodHandle PGC_N = dropNameAndArgs(PGC, 4, -1, false); private static final MethodHandle GETMETHOD_N = dropNameAndArgs(GETMETHOD, 5, -1, false); private static final MethodHandle TEST_N = dropNameAndArgs(TEST, 4, -1, false); private static final MethodHandle TARGET_N; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject[].class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject[].class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject[].class), new int[] {0, 3, 5, 1, 6, 7}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_N); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_N); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args TARGET_N = target; } private static final MethodHandle FALLBACK_N = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject[].class)); private static final MethodHandle BREAKJUMP; static { MethodHandle breakJump = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "handleBreakJump", MethodType.make( IRubyObject.class, JumpException.BreakJump.class, ThreadContext.class)); // BreakJump, ThreadContext breakJump = MethodHandles.permuteArguments( breakJump, MethodType.make( IRubyObject.class, JumpException.BreakJump.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {0, 2}); // BreakJump, CacheEntry, ThreadContext, IRubyObject, IRubyObject BREAKJUMP = breakJump; } private static final MethodHandle RETRYJUMP; static { MethodHandle retryJump = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "retryJumpError", MethodType.make(IRubyObject.class, ThreadContext.class)); // ThreadContext retryJump = MethodHandles.permuteArguments( retryJump, MethodType.make( IRubyObject.class, JumpException.RetryJump.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class), new int[] {2}); // RetryJump, CacheEntry, ThreadContext, IRubyObject, IRubyObject RETRYJUMP = retryJump; } private static final MethodHandle PGC_0_B = dropNameAndArgs(PGC, 4, 0, true); private static final MethodHandle GETMETHOD_0_B = dropNameAndArgs(GETMETHOD, 5, 0, true); private static final MethodHandle TEST_0_B = dropNameAndArgs(TEST, 4, 0, true); private static final MethodHandle TARGET_0_B; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, Block.class), new int[] {0, 3, 5, 1, 6, 7}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_0_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_0_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, 0, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, 0, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_0_B = target; } private static final MethodHandle FALLBACK_0_B = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, Block.class)); private static final MethodHandle PGC_1_B = dropNameAndArgs(PGC, 4, 1, true); private static final MethodHandle GETMETHOD_1_B = dropNameAndArgs(GETMETHOD, 5, 1, true); private static final MethodHandle TEST_1_B = dropNameAndArgs(TEST, 4, 1, true); private static final MethodHandle TARGET_1_B; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, Block.class), new int[] {0, 3, 5, 1, 6, 7, 8}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_1_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_1_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, 1, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, 1, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_1_B = target; } private static final MethodHandle FALLBACK_1_B = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, Block.class)); private static final MethodHandle PGC_2_B = dropNameAndArgs(PGC, 4, 2, true); private static final MethodHandle GETMETHOD_2_B = dropNameAndArgs(GETMETHOD, 5, 2, true); private static final MethodHandle TEST_2_B = dropNameAndArgs(TEST, 4, 2, true); private static final MethodHandle TARGET_2_B; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, Block.class), new int[] {0, 3, 5, 1, 6, 7, 8, 9}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_2_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_2_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, 2, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, 2, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_2_B = target; } private static final MethodHandle FALLBACK_2_B = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, Block.class)); private static final MethodHandle PGC_3_B = dropNameAndArgs(PGC, 4, 3, true); private static final MethodHandle GETMETHOD_3_B = dropNameAndArgs(GETMETHOD, 5, 3, true); private static final MethodHandle TEST_3_B = dropNameAndArgs(TEST, 4, 3, true); private static final MethodHandle TARGET_3_B; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class), new int[] {0, 3, 5, 1, 6, 7, 8, 9, 10}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_3_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_3_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, 3, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, 3, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_3_B = target; } private static final MethodHandle FALLBACK_3_B = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class)); private static final MethodHandle PGC_N_B = dropNameAndArgs(PGC, 4, -1, true); private static final MethodHandle GETMETHOD_N_B = dropNameAndArgs(GETMETHOD, 5, -1, true); private static final MethodHandle TEST_N_B = dropNameAndArgs(TEST, 4, -1, true); private static final MethodHandle TARGET_N_B; static { MethodHandle target = MethodHandles.lookup() .findVirtual( DynamicMethod.class, "call", MethodType.make( IRubyObject.class, ThreadContext.class, IRubyObject.class, RubyModule.class, String.class, IRubyObject[].class, Block.class)); target = MethodHandles.convertArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, ThreadContext.class, IRubyObject.class, RubyClass.class, String.class, IRubyObject[].class, Block.class)); target = MethodHandles.permuteArguments( target, MethodType.make( IRubyObject.class, DynamicMethod.class, RubyClass.class, CacheEntry.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject[].class, Block.class), new int[] {0, 3, 5, 1, 6, 7, 8}); // IRubyObject, DynamicMethod, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, // String, args target = MethodHandles.foldArguments(target, GETMETHOD_N_B); // IRubyObject, RubyClass, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args target = MethodHandles.foldArguments(target, PGC_N_B); // IRubyObject, CacheEntry, ThreadContext, IRubyObject, IRubyObject, String, args MethodHandle breakJump = dropNameAndArgs(BREAKJUMP, 5, -1, true); MethodHandle retryJump = dropNameAndArgs(RETRYJUMP, 5, -1, true); target = MethodHandles.catchException(target, JumpException.BreakJump.class, breakJump); target = MethodHandles.catchException(target, JumpException.RetryJump.class, retryJump); TARGET_N_B = target; } private static final MethodHandle FALLBACK_N_B = MethodHandles.lookup() .findStatic( InvokeDynamicSupport.class, "fallback", MethodType.make( IRubyObject.class, JRubyCallSite.class, ThreadContext.class, IRubyObject.class, IRubyObject.class, String.class, IRubyObject[].class, Block.class)); }