----- Original Message ----- From: "Alessio Stalla" alessiostalla@gmail.com To: dmiles@users.sourceforge.net Cc: "Armed Bear" armedbear-devel@common-lisp.net Sent: Tuesday, November 10, 2009 1:12 AM Subject: Re: [armedbear-devel] Inline primitives as static method calls
On Tue, Nov 10, 2009 at 9:01 AM, logicmoo@gmail.com wrote:
Alessio, Excellent Work!
Your .patch is what I meant.
Thanks!
when compiled it is translated as a direct call to the static method, without passing through the symbol, which is faster than now
Perfect - Yeah
A Side note:
When interpreted or passed as a higher-order function an InlinedPrimitive calls the static method through reflection, resulting in slower performance than now.
I wrote a workaround for this into LarKC because of the performance degradation.
So later on.... Like after we have everything working/vetted calling static inlines as much as possible. And using InlinePrimtives to call reflection...
We'll have some options like: "FixedArityFunctor":
http://larkc.svn.sourceforge.net/viewvc/larkc/trunk/platform/src/com/cyc/too...
What I did was created a new Class via ASM that contains a single execute(a,b,c,d,e,f) signature per "args used". That simply calls the static method .
So in InlinePrimitive later suplimented with some extras like:
//The methodWith0Args - methodWithNArgs is what that .java url above generates. LispObject execute() { return methodWith0Args.evaluate(); } LispObject execute(LispObject a0) { return methodWith1Args.evaluate(a0); } LispObject execute(LispObject a0,LispObject a1) { return methodWith2Args.evaluate(a0,a1); } etc
Figured I should mention the "FixedArityFunctor" so we dont get scared off by any performance degration of higher level calls before we learn all the benefits of inlining static functions!
Ok, I'm not sure I followed everything.
Oh the above was attempting to describe LarKC SubLisp implementation of this article: http://www.ibm.com/developerworks/java/library/j-dyn0610/ I couldnt find it before sending the email! The intial LarKC implemention used reflection in the same maner as InlinedPrimive does. The after reading that article, I found I could replace Method[] cache inside InlinedPrimive with generated methodStubs produced runtime for reflection performance.
but consider also that the implementation through reflection is the default one, for convenience, but you can still override the various execute() methods and call the static method directly (of course, you have to make sure the method you call is the same as the one you pass in the constructor, or things start to behave differently in interpreted vs compiled code and that's definitely not good :D). Something like
new InlinedPrimitive(My.class, "myMethod", ...) { public LispObject execute(LispObject arg) { return My.myMethod(arg); } }
Yup, InlinePrimtive still leaves that option open. If someone really wanted to, they can do that with a couple of their InlinedPrimtives if they noticed one particualtar method was getting called quite a bit. Making the instance execute call the static function (Like EQ/EQL/EQUAL for instance avoiding reflection.)
The class I posted lacks the constructors taking the class and the method, because I have been lazy ;), but they can easily be added - with the caveat that, since the call to super() must be the first and for Function super() sometimes (always?) installs the function in a symbol (iirc), if you pass a wrong class/method to InlinedPrimitive and as a result an exception is thrown, you'll have a symbol pointing to an invalid function.
I realy do like how you did it as factory method:
public static final Primitive COPY_TREE = InlinedPrimitive.get(Primitives.class, "copyTree", Symbol.COPY_TREE, "object");
And depending on safety/speed you could save the string name of the class and method name for later and not even try to resolve the method[] until first time call.. and signal an error then if not found. This could be used like autoloading.
Bye, Ale