public GuardBuilder permute(int... reorder) { binder = binder.permute(reorder); return this; } }
public GuardBuilder guard(int... reorder) { return new GuardBuilder(this, this.binder.guardBinder().permute(reorder)); }
/** * Using the argument names and order in the target Signature, permute the * arguments in this SmartBinder. Arguments may be duplicated or omitted * in the target Signature, but all arguments in the target must be defined * in this SmartBinder . * * @param target the Signature from which to derive a new argument list * @return a new SmartBinder with the permute applied */ public SmartBinder permute(Signature target) { return new SmartBinder(this, target, binder.permute(signature().to(target))); }
@Override public MethodHandle guardMethodHandle(MethodType inputType) throws NoSuchMethodException, IllegalAccessException { Binder binder = Binder.from(inputType); MethodHandle target = super.guardMethodHandle(methodType(boolean.class, this.argType)); return binder.permute(this.argPos) .convert(target.type()) .invoke(target); }
@Override public MethodHandle guardMethodHandle(MethodType inputType) throws NoSuchMethodException, IllegalAccessException { Binder binder = Binder.from(inputType); MethodHandle target = super.guardMethodHandle(methodType(boolean.class, this.argType)); return binder.permute(this.argPos) .convert(target.type()) .invoke(target); }
@Override public MethodHandle generate(JRubyCallSite site, RubyClass cls, DynamicMethod method, String realName) { MethodHandle handle = ((HandleMethod)method).getHandle(site.arity()); if (handle == null) { throw new IndirectBindingException("MH dynamic method does not have needed arity"); } if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name() + "\tbound from MHDynMethod " + logMethod(method) + ":" + handle); Signature fullSig = site.fullSignature(); MethodHandle nativeTarget = Binder .from(fullSig.type()) .permute(fullSig.to("context", "self", "arg*", "block")) .invoke(handle); nativeTarget = addOrRemoveBlock(site, nativeTarget); return nativeTarget; } }
@Override public MethodHandle generate(JRubyCallSite site, RubyClass cls, DynamicMethod method, String realName) { MethodHandle handle = ((HandleMethod)method).getHandle(site.arity()); if (handle == null) { throw new IndirectBindingException("MH dynamic method does not have needed arity"); } if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name() + "\tbound from MHDynMethod " + logMethod(method) + ":" + handle); Signature fullSig = site.fullSignature(); MethodHandle nativeTarget = Binder .from(fullSig.type()) .permute(fullSig.to("context", "self", "arg*", "block")) .invoke(handle); nativeTarget = addOrRemoveBlock(site, nativeTarget); return nativeTarget; } }
private MethodHandle nativeTryFinally(MethodHandle target, MethodHandle post) { MethodType targetType = target.type(); boolean voidReturn = targetType.returnType() == Void.TYPE; MethodType finallyType = targetType.insertParameterTypes(0, Throwable.class); int dropCount = 1; if (!voidReturn) { finallyType = finallyType.insertParameterTypes(1, targetType.returnType()); dropCount = 2; } MethodHandle wrapPost = Binder .from(finallyType) .drop(0, dropCount) .invoke(post); if (!voidReturn) { wrapPost = Binder.from(finallyType) .foldVoid(wrapPost) .permute(1) .identity(); } try { return (MethodHandle) tryFinallyJava9.invokeExact(target, wrapPost); } catch (Throwable t) { throw new RuntimeException("Java 9 detected but MethodHandles.tryFinally missing", t); } }
public static MethodHandle wrapWithFrameOnly(Signature signature, RubyModule implClass, String name, MethodHandle nativeTarget) { MethodHandle framePre = getFrameOnlyPre(signature, CallConfiguration.FrameFullScopeNone, implClass, name); MethodHandle framePost = getFramePost(signature, CallConfiguration.FrameFullScopeNone); // post logic for frame nativeTarget = Binder .from(nativeTarget.type()) .tryFinally(framePost) .invoke(nativeTarget); // pre logic for frame nativeTarget = foldArguments(nativeTarget, framePre); // call polling and call number increment nativeTarget = Binder .from(nativeTarget.type()) .fold(Binder .from(nativeTarget.type().changeReturnType(void.class)) .permute(0) .invokeStaticQuiet(lookup(), ThreadContext.class, "callThreadPoll")) .invoke(nativeTarget); return nativeTarget; }
public static MethodHandle wrapWithFrameOnly(Signature signature, RubyModule implClass, String name, MethodHandle nativeTarget) { MethodHandle framePre = getFrameOnlyPre(signature, CallConfiguration.FrameFullScopeNone, implClass, name); MethodHandle framePost = getFramePost(signature, CallConfiguration.FrameFullScopeNone); // post logic for frame nativeTarget = Binder .from(nativeTarget.type()) .tryFinally(framePost) .invoke(nativeTarget); // pre logic for frame nativeTarget = foldArguments(nativeTarget, framePre); // call polling and call number increment nativeTarget = Binder .from(nativeTarget.type()) .fold(Binder .from(nativeTarget.type().changeReturnType(void.class)) .permute(0) .invokeStaticQuiet(lookup(), ThreadContext.class, "callThreadPoll")) .invoke(nativeTarget); return nativeTarget; }
public static MethodHandle wrapWithFraming(Signature signature, CallConfiguration callConfig, RubyModule implClass, String name, MethodHandle nativeTarget, StaticScope scope) { MethodHandle framePre = getFramePre(signature, callConfig, implClass, name, scope); if (framePre != null) { MethodHandle framePost = getFramePost(signature, callConfig); // break, return, redo handling boolean heapScoped = callConfig.scoping() != Scoping.None; boolean framed = callConfig.framing() != Framing.None; // post logic for frame nativeTarget = Binder .from(nativeTarget.type()) .tryFinally(framePost) .invoke(nativeTarget); // pre logic for frame nativeTarget = foldArguments(nativeTarget, framePre); // call polling and call number increment nativeTarget = Binder .from(nativeTarget.type()) .fold(Binder .from(nativeTarget.type().changeReturnType(void.class)) .permute(0) .invokeStaticQuiet(lookup(), ThreadContext.class, "callThreadPoll")) .invoke(nativeTarget); } return nativeTarget; }
public static MethodHandle wrapWithFraming(Signature signature, CallConfiguration callConfig, RubyModule implClass, String name, MethodHandle nativeTarget, StaticScope scope) { MethodHandle framePre = getFramePre(signature, callConfig, implClass, name, scope); if (framePre != null) { MethodHandle framePost = getFramePost(signature, callConfig); // break, return, redo handling boolean heapScoped = callConfig.scoping() != Scoping.None; boolean framed = callConfig.framing() != Framing.None; // post logic for frame nativeTarget = Binder .from(nativeTarget.type()) .tryFinally(framePost) .invoke(nativeTarget); // pre logic for frame nativeTarget = foldArguments(nativeTarget, framePre); // call polling and call number increment nativeTarget = Binder .from(nativeTarget.type()) .fold(Binder .from(nativeTarget.type().changeReturnType(void.class)) .permute(0) .invokeStaticQuiet(lookup(), ThreadContext.class, "callThreadPoll")) .invoke(nativeTarget); } return nativeTarget; }
public IRubyObject yieldSpecific(ThreadContext context, Block block) throws Throwable { if (Options.INVOKEDYNAMIC_YIELD.load()) { BlockBody body = block.getBody(); MethodHandle target; if (block.getBody() instanceof CompiledIRBlockBody) { CompiledIRBlockBody compiledBody = (CompiledIRBlockBody) block.getBody(); if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) { LOG.info("yield \tbound directly as yieldSpecific:" + Bootstrap.logBlock(block)); } target = compiledBody.getNormalYieldSpecificHandle(); } else { if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) { LOG.info("yield \tbound indirectly as yieldSpecific:" + Bootstrap.logBlock(block)); } target = Binder.from(type()) .permute(1, 0) .invokeVirtualQuiet(MethodHandles.lookup(), "yieldSpecific"); } MethodHandle fallback = getTarget(); MethodHandle test = body.getTestBlockBody(); MethodHandle guard = MethodHandles.guardWithTest(test, target, fallback); setTarget(guard); return (IRubyObject) target.invokeExact(context, block); } return block.yieldSpecific(context); }
public IRubyObject yieldSpecific(ThreadContext context, Block block) throws Throwable { if (Options.INVOKEDYNAMIC_YIELD.load()) { BlockBody body = block.getBody(); MethodHandle target; if (block.getBody() instanceof CompiledIRBlockBody) { CompiledIRBlockBody compiledBody = (CompiledIRBlockBody) block.getBody(); if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) { LOG.info("yield \tbound directly as yieldSpecific:" + Bootstrap.logBlock(block)); } target = compiledBody.getNormalYieldSpecificHandle(); } else { if (Options.INVOKEDYNAMIC_LOG_BINDING.load()) { LOG.info("yield \tbound indirectly as yieldSpecific:" + Bootstrap.logBlock(block)); } target = Binder.from(type()) .permute(1, 0) .invokeVirtualQuiet(MethodHandles.lookup(), "yieldSpecific"); } MethodHandle fallback = getTarget(); MethodHandle test = body.getTestBlockBody(); MethodHandle guard = MethodHandles.guardWithTest(test, target, fallback); setTarget(guard); return (IRubyObject) target.invokeExact(context, block); } return block.yieldSpecific(context); }