Am I right that the goal of this would be to allow for specific Ruby calls to be sped up by skipping a lot of the dynamic nature of the language? Assuming that's true, what I was hoping for would be a non-invasive way of adding functionality like to without breaking my ability to still run the code on MRI. In my ideal world I would be able to add "hints" to JRuby to speed things up in a normally unsafe way, but not have to change the actual code so that if I still wanted to run on MRI I could, these special optimizations would just not be used. Maybe something in a comment?
Joe On Sun, Apr 12, 2009 at 2:15 AM, Charles Oliver Nutter < [email protected]> wrote: > Attached is a patch that adds the ability to make *static* calls in > compiled code. Basically the compiler sees it and makes it a static > invocation instead of a dynamic one. It's pretty ugly though, since you need > to specify all the Java signature stuff: > > To make "n - 2" into a static call against RubyFixnum, you'd use: > > __static_call__("org/jruby/RubyFixnum", n, "op_minus", > "(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject;", > 2) > > The compiler would then evaluate n, cast it to RubyFixnum, evaluate the > arguments, and make the call directly. > > A better syntax would probably make this more usable, but in my testing I > have not seen it make a substantial performance difference. Our call > pipeline, once compiled, appears to be pretty darn good. > > At any rate, the patch is attached for posterity. I'd love to hear about > other ideas for this. > > - Charlie > > diff --git a/src/org/jruby/compiler/ASTCompiler.java > b/src/org/jruby/compiler/ASTCompiler.java > index 5a75698..5597062 100644 > --- a/src/org/jruby/compiler/ASTCompiler.java > +++ b/src/org/jruby/compiler/ASTCompiler.java > @@ -2120,6 +2120,11 @@ public class ASTCompiler { > public void compileFCall(Node node, BodyCompiler context, boolean expr) > { > final FCallNode fcallNode = (FCallNode) node; > > + if (fcallNode.getName().equals("__static_call__")) { > + compileStaticCall(fcallNode, context, expr); > + return; > + } > + > ArgumentsCallback argsCallback = > getArgsCallback(fcallNode.getArgsNode()); > > CompilerCallback closureArg = getBlock(fcallNode.getIterNode()); > @@ -2129,6 +2134,35 @@ public class ASTCompiler { > if (!expr) context.consumeCurrentValue(); > } > > + public void compileStaticCall(FCallNode fcallNode, BodyCompiler > context, boolean expr) { > + ArrayNode args = (ArrayNode)fcallNode.getArgsNode(); > + > + // args[0] is the Java type to cast to > + StrNode type = (StrNode)args.get(0); > + > + // args[1] is the receiver node > + final Node receiver = args.get(1); > + > + // args[2] is the method name > + StrNode method = (StrNode)args.get(2); > + > + // args[3] is the signature > + StrNode signature = (StrNode)args.get(3); > + > + // args[4] is the expression to produce all arguments > + final Node callArgs = args.get(4); > + > + CompilerCallback receiverCallback = new CompilerCallback() { > + public void call(BodyCompiler context) { > + compile(receiver, context, true); > + } > + }; > + > + ArgumentsCallback argsCallback = getArgsCallback(callArgs); > + > + context.compileStaticCall(receiverCallback, argsCallback, > type.getValue().toString(), method.getValue().toString(), > signature.getValue().toString()); > + } > + > private CompilerCallback getBlock(Node node) { > if (node == null) { > return null; > @@ -2543,27 +2577,23 @@ public class ASTCompiler { > public void compileIter(Node node, BodyCompiler context) { > final IterNode iterNode = (IterNode) node; > > - // create the closure class and instantiate it > final CompilerCallback closureBody = new CompilerCallback() { > + public void call(BodyCompiler context) { > + if (iterNode.getBodyNode() != null) { > + compile(iterNode.getBodyNode(), context, true); > + } else { > + context.loadNil(); > + } > + } > + }; > > - public void call(BodyCompiler context) { > - if (iterNode.getBodyNode() != null) { > - compile(iterNode.getBodyNode(), context, > true); > - } else { > - context.loadNil(); > - } > - } > - }; > - > - // create the closure class and instantiate it > final CompilerCallback closureArgs = new CompilerCallback() { > - > - public void call(BodyCompiler context) { > - if (iterNode.getVarNode() != null) { > - compileAssignment(iterNode.getVarNode(), > context, false); > - } > - } > - }; > + public void call(BodyCompiler context) { > + if (iterNode.getVarNode() != null) { > + compileAssignment(iterNode.getVarNode(), context, > false); > + } > + } > + }; > > boolean hasMultipleArgsHead = false; > if (iterNode.getVarNode() instanceof MultipleAsgnNode) { > diff --git a/src/org/jruby/compiler/BodyCompiler.java > b/src/org/jruby/compiler/BodyCompiler.java > index 94f501d..65d3213 100644 > --- a/src/org/jruby/compiler/BodyCompiler.java > +++ b/src/org/jruby/compiler/BodyCompiler.java > @@ -587,4 +587,6 @@ public interface BodyCompiler { > List<ArgumentsCallback> conditionals, > List<CompilerCallback> bodies, > CompilerCallback fallback); > + > + public void compileStaticCall(CompilerCallback receiver, > ArgumentsCallback args, String type, String method, String signature); > } > diff --git a/src/org/jruby/compiler/impl/BaseBodyCompiler.java > b/src/org/jruby/compiler/impl/BaseBodyCompiler.java > index 56ab7d2..63fc794 100644 > --- a/src/org/jruby/compiler/impl/BaseBodyCompiler.java > +++ b/src/org/jruby/compiler/impl/BaseBodyCompiler.java > @@ -2532,4 +2532,12 @@ public abstract class BaseBodyCompiler implements > BodyCompiler { > > getVariableCompiler().releaseTempLocal(); > } > + > + public void compileStaticCall(CompilerCallback receiver, > ArgumentsCallback args, String type, String methodName, String signature) { > + receiver.call(this); > + method.checkcast(type); > + if (signature.startsWith("(Lorg/jruby/runtime/ThreadContext;")) > loadThreadContext(); > + args.call(this); > + method.invokevirtual(type, methodName, signature); > + } > } > \ No newline at end of file > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > >
