public JittedMethod(RubyModule implementationClass, StaticScope staticScope, Script jitCompiledScript, String name, CallConfiguration jitCallConfig, Visibility visibility, Arity arity, ISourcePosition position, DefaultMethod realMethod) { super(implementationClass, visibility, jitCallConfig, name); this.position = position; this.jitCompiledScript = jitCompiledScript; this.staticScope = staticScope; this.arity = arity; this.realMethod = realMethod; int argCount = arity.getValue(); if (argCount < 0 || argCount > 3) argCount = 4; this.nativeCall = new NativeCall( jitCompiledScript.getClass(), "__file__", IRubyObject.class, StandardASMCompiler.getStaticMethodParams(jitCompiledScript.getClass(), argCount), true); }
boolean isStatic = nativeCall.isStatic(); Class[] signature = nativeCall.getNativeSignature(); if (signature.length > 0 && signature[signature.length - 1].isArray()) { return null; MethodType apparentType = methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature()); nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType);
boolean isStatic = nativeCall.isStatic(); if (site.arity != nativeCall.getNativeSignature().length - 1) { return null; } else if (site.arity != nativeCall.getNativeSignature().length) { return null; Class[] signature = nativeCall.getNativeSignature(); if (signature.length > 0 && signature[signature.length - 1].isArray()) { return null; MethodType apparentType = methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature()); nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType);
boolean isStatic = nativeCall.isStatic(); if (site.arity != nativeCall.getNativeSignature().length - 1) { return null; } else if (site.arity != nativeCall.getNativeSignature().length) { return null; Class[] signature = nativeCall.getNativeSignature(); if (signature.length > 0 && signature[signature.length - 1].isArray()) { return null; MethodType apparentType = methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature()); nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType);
boolean isStatic = nativeCall.isStatic(); Class[] signature = nativeCall.getNativeSignature(); if (signature.length > 0 && signature[signature.length - 1].isArray()) { return null; MethodType apparentType = methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature()); nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType);
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, Block.NULL_BLOCK); } 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()); if (b.type().parameterCount() == nc.getNativeSignature().length + 1) { .cast(MethodType.methodType(nc.getNativeReturn(), nc.getNativeTarget(), nc.getNativeSignature())) .invokeVirtualQuiet(MethodHandles.lookup(), nc.getNativeName());
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, Block.NULL_BLOCK); } 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()); if (b.type().parameterCount() == nc.getNativeSignature().length + 1) { .cast(MethodType.methodType(nc.getNativeReturn(), nc.getNativeTarget(), nc.getNativeSignature())) .invokeVirtualQuiet(MethodHandles.lookup(), nc.getNativeName());
if (nc.isJava()) { return createJavaHandle(site, method); } else { if (!nc.hasContext()) { binder = binder.drop("context"); if (nc.hasBlock() && !blockGiven) { binder = binder.append("block", Block.NULL_BLOCK); } else if (!nc.hasBlock() && blockGiven) { binder = binder.drop("block"); if (nc.isStatic()) { mh = binder .permute("context", "self", "arg.*", "block") // filter caller .cast(nc.getNativeReturn(), nc.getNativeSignature()) .invokeStaticQuiet(LOOKUP, nc.getNativeTarget(), nc.getNativeName()) .handle(); } else { mh = binder .permute("self", "context", "arg.*", "block") // filter caller, move self .castArg("self", nc.getNativeTarget()) .castVirtual(nc.getNativeReturn(), nc.getNativeTarget(), nc.getNativeSignature()) .invokeVirtualQuiet(LOOKUP, nc.getNativeName()) .handle(); JRubyMethod anno = nativeCall.getMethod().getAnnotation(JRubyMethod.class); if (anno != null && anno.frame()) { mh = InvocationLinker.wrapWithFrameOnly(site.signature, method.getImplementationClass(), site.name(), mh);
if (nc.isJava()) { return createJavaHandle(site, method); } else { if (!nc.hasContext()) { binder = binder.drop("context"); if (nc.hasBlock() && !blockGiven) { binder = binder.append("block", Block.NULL_BLOCK); } else if (!nc.hasBlock() && blockGiven) { binder = binder.drop("block"); if (nc.isStatic()) { mh = binder .permute("context", "self", "arg.*", "block") // filter caller .cast(nc.getNativeReturn(), nc.getNativeSignature()) .invokeStaticQuiet(LOOKUP, nc.getNativeTarget(), nc.getNativeName()) .handle(); } else { mh = binder .permute("self", "context", "arg.*", "block") // filter caller, move self .castArg("self", nc.getNativeTarget()) .castVirtual(nc.getNativeReturn(), nc.getNativeTarget(), nc.getNativeSignature()) .invokeVirtualQuiet(LOOKUP, nc.getNativeName()) .handle(); JRubyMethod anno = nativeCall.getMethod().getAnnotation(JRubyMethod.class); if (anno != null && anno.frame()) { mh = InvocationLinker.wrapWithFrameOnly(site.signature, method.getImplementationClass(), site.name(), mh);
Class[] nativeSig = nativeCall.getNativeSignature(); boolean isStatic = nativeCall.isStatic(); nativeCall.getNativeTarget(), nativeCall.getNativeName(), methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature())); } else { nativeTarget = site.lookup().findVirtual( nativeCall.getNativeTarget(), nativeCall.getNativeName(), methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature())); if (nativeCall.getNativeReturn() == void.class) { nativeTarget = filterReturnValue(nativeTarget, constant(IRubyObject.class, runtime.getNil()));
Class[] nativeSig = nativeCall.getNativeSignature(); boolean isStatic = nativeCall.isStatic(); nativeCall.getNativeTarget(), nativeCall.getNativeName(), methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature())); } else { nativeTarget = site.lookup().findVirtual( nativeCall.getNativeTarget(), nativeCall.getNativeName(), methodType(nativeCall.getNativeReturn(), nativeCall.getNativeSignature())); if (nativeCall.getNativeReturn() == void.class) { nativeTarget = filterReturnValue(nativeTarget, constant(IRubyObject.class, runtime.getNil()));
Method javaMethod = nativeCall.getMethod(); JRubyMethod anno = javaMethod.getAnnotation(JRubyMethod.class);
Method reflected = method.getNativeCall().getMethod(); JRubyMethod annotation = reflected.getAnnotation(JRubyMethod.class);
Method reflected = method.getNativeCall().getMethod(); JRubyMethod annotation = reflected.getAnnotation(JRubyMethod.class);
Method javaMethod = nativeCall.getMethod(); JRubyMethod anno = javaMethod.getAnnotation(JRubyMethod.class);
int argCount = getRubyArgCount(nativeCall.getNativeSignature()); .permute(fullSig.to("context", "self", "arg*", "block")) .insert(0, scriptObject) .invokeStaticQuiet(site.lookup(), nativeCall.getNativeTarget(), nativeCall.getNativeName());
int argCount = getRubyArgCount(nativeCall.getNativeSignature()); .permute(fullSig.to("context", "self", "arg*", "block")) .insert(0, scriptObject) .invokeStaticQuiet(site.lookup(), nativeCall.getNativeTarget(), nativeCall.getNativeName());
@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; }
/** * Set the single-arity NativeCall for this method. All signatures for the * non-single-arity getNativeCall will also be set to this value. * * @param nativeTarget native method target * @param nativeName native method name * @param nativeReturn native method return * @param nativeSignature native method arguments * @param statik static? * @param java plain Java method? */ public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik, boolean java) { this.nativeCall = new NativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, java); Arrays.fill(nativeCalls, nativeCall); }