@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (nativeCall != null) { int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); // arity must match or both be [] args if (nativeArgCount != site.arity()) { throw new IndirectBindingException("arity mismatch or varargs at call site: " + nativeArgCount + " != " + site.arity()); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (nativeCall != null) { int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); // arity must match or both be [] args if (nativeArgCount != site.arity()) { throw new IndirectBindingException("arity mismatch or varargs at call site: " + nativeArgCount + " != " + site.arity()); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (method instanceof CompiledMethod || method instanceof JittedMethod) { if (nativeCall != null) { int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); // arity must match or both be [] args if (nativeArgCount != site.arity()) { throw new IndirectBindingException("arity mismatch or varargs at call site: " + nativeArgCount + " != " + site.arity()); } return true; } } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (method instanceof CompiledMethod || method instanceof JittedMethod) { if (nativeCall != null) { int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); // arity must match or both be [] args if (nativeArgCount != site.arity()) { throw new IndirectBindingException("arity mismatch or varargs at call site: " + nativeArgCount + " != " + site.arity()); } return true; } } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof AttrWriterMethod) { // attr writer if (!RubyInstanceConfig.INVOKEDYNAMIC_ATTR) { throw new IndirectBindingException("direct attribute dispatch not enabled"); } if (site.arity() != 1) { throw new IndirectBindingException("attr writer with > 1 args"); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof AttrReaderMethod) { // attr reader if (!RubyInstanceConfig.INVOKEDYNAMIC_ATTR) { throw new IndirectBindingException("direct attribute dispatch not enabled"); } if (site.arity() != 0) { throw new IndirectBindingException("attr reader with > 0 args"); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof AttrReaderMethod) { // attr reader if (!RubyInstanceConfig.INVOKEDYNAMIC_ATTR) { throw new IndirectBindingException("direct attribute dispatch not enabled"); } if (site.arity() != 0) { throw new IndirectBindingException("attr reader with > 0 args"); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof AttrWriterMethod) { // attr writer if (!RubyInstanceConfig.INVOKEDYNAMIC_ATTR) { throw new IndirectBindingException("direct attribute dispatch not enabled"); } if (site.arity() != 1) { throw new IndirectBindingException("attr writer with > 1 args"); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (nativeCall != null) { // has an explicit native call path if (nativeCall.isJava()) { if (!RubyInstanceConfig.INVOKEDYNAMIC_JAVA) { throw new IndirectBindingException("direct Java dispatch not enabled"); } // if Java, must: // * match arity <= 3 // * not be passed a block (no coercion yet) // * be a normal wrapper around a class or module (not a Ruby subclass) if (nativeCall.getNativeSignature().length != site.arity() || site.arity() > 3 || site.isIterator() || !cls.getJavaProxy()) { throw new IndirectBindingException("Java call arity mismatch or > 3 args"); } return true; } } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { NativeCall nativeCall = method.getNativeCall(); if (nativeCall != null) { // has an explicit native call path if (nativeCall.isJava()) { if (!RubyInstanceConfig.INVOKEDYNAMIC_JAVA) { throw new IndirectBindingException("direct Java dispatch not enabled"); } // if Java, must: // * match arity <= 3 // * not be passed a block (no coercion yet) // * be a normal wrapper around a class or module (not a Ruby subclass) if (nativeCall.getNativeSignature().length != site.arity() || site.arity() > 3 || site.isIterator() || !cls.getJavaProxy()) { throw new IndirectBindingException("Java call arity mismatch or > 3 args"); } return true; } } return false; }
@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; } }
int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); if (nativeArgCount == 4 && site.arity() == 4) {
int nativeArgCount = getNativeArgCount(method, method.getNativeCall()); if (nativeArgCount == 4 && site.arity() == 4) {
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof org.jruby.ext.ffi.jffi.DefaultMethod || method instanceof org.jruby.ext.ffi.jffi.JITNativeInvoker) { // if frame/scope required, can't dispatch direct if (method.getCallConfig() != CallConfiguration.FrameNoneScopeNone) { throw new IndirectBindingException("frame or scope required: " + method.getCallConfig()); } if (!method.getArity().isFixed()) { throw new IndirectBindingException("fixed arity required: " + method.getArity()); } // Arity must match, otherwise let the indirect method process errors if (method.getArity().getValue() != site.arity()) { throw new IndirectBindingException("arity mismatch"); } // Only support 0..6 parameters if (method.getArity().getValue() > 6) { throw new IndirectBindingException("target args > 6"); } if (site.type().parameterType(site.type().parameterCount() - 1) == Block.class) { // Called with a block to substitute for a callback param - cannot bind directly throw new IndirectBindingException("callback block supplied"); } return true; } return false; }
@Override public boolean canGenerate(JRubyCallSite site, RubyClass cls, DynamicMethod method) { if (method instanceof org.jruby.ext.ffi.jffi.DefaultMethod || method instanceof org.jruby.ext.ffi.jffi.JITNativeInvoker) { // if frame/scope required, can't dispatch direct if (method.getCallConfig() != CallConfiguration.FrameNoneScopeNone) { throw new IndirectBindingException("frame or scope required: " + method.getCallConfig()); } if (!method.getArity().isFixed()) { throw new IndirectBindingException("fixed arity required: " + method.getArity()); } // Arity must match, otherwise let the indirect method process errors if (method.getArity().getValue() != site.arity()) { throw new IndirectBindingException("arity mismatch"); } // Only support 0..6 parameters if (method.getArity().getValue() > 6) { throw new IndirectBindingException("target args > 6"); } if (site.type().parameterType(site.type().parameterCount() - 1) == Block.class) { // Called with a block to substitute for a callback param - cannot bind directly throw new IndirectBindingException("callback block supplied"); } return true; } return false; }