Thanks very much Kresten. That satisfies my curiousity, and it makes perfect sense that you'd get performance close to the JRuby dynopt version with the way this compiles. It makes me wish Ruby were as straightforward at times :)
I also see something else I find interesting: EObject apparently implements dec() and is_ge()...I'm guessing you have implemented a full set of numeric operators on EObject so that when they're explicitly provided by a subtype it can be no more than an interface or abstract dispatch? We've thought of doing the same for JRuby, but were unsure whether it would be too cumbersome. The essential idea would be that the default implementations would proceed to doing a dynamic dispatch while the overridden versions would provide the implementation in-place, perhaps with a guard in case someone monkey-patched them. It would reduce most math operators against core types to static calls (+ a two-field object comparison for the guard) and greatly improve their inlinability. Is that what you've done and why you've done it for Erjang? On Sat, Jun 5, 2010 at 11:13 AM, Kresten Krab Thorup <[email protected]> wrote: > For reference, here's the bytecode for tak in Erjang [JAD'ed bytecode > even further below]. > > In the actual generated code, it moves things around quite a bit in > local variables, but that is because of the way I translate BEAM to > JVM by keeping a "stack" in the local variables. All function calls > then do aload_0, aload_1, ... aload_N before a function call with > N-1. I'm assuming that the JVM will see through all these register > moves and optimize them away. > > tak is very easy to translate for Erjang, because a simple local > analysis says that it doesn't suspend. So because of that it > generates very straightforward code. This is often the case for > "leafs" in the call graph. > > Except for all the extra moving things around in variables, this is > what it does. The only "issue" with this is that Erjang cannot > suspend the thread while running in this loop (i.e. Kilim is not > pushed on this code). The check_exit() at the end of the loop is > there to make sure I can kill the process. is_ge() and dec() > [decrement] are native method on EObject. > > static EObject tak(EProc proc, EObject X, EObject Y, EObject Z) > { > do { > if (Y.is_ge(X)) { return Z; } > EObject X1 = tak(proc, X.dec(), Y, Z); > EObject Y1 = tak(proc, Y.dec(), Z, X); > EObject Z1 = tak(proc, Z.dec(), X, Y); > X = X1; Y = Y1; Z = Z1; > proc.check_exit(); > } while (true); > } > > Kresten > > > > -----[actual generated code]---- > Method name:"tak__3" public static Signature: > (erjang.EProc,erjang.EObject,erjang.EObject,erjang.EObject)erjang.EObject > Attribute "Code", length:170, max_stack:4, max_locals:9, code_length: > 138 > 0: goto 3 > 3: aload_2 > 4: aload_1 > 5: invokevirtual <Method erjang.EObject.is_ge > (erjang.EObject)boolean> > 8: ifeq 15 > 11: aload_3 > 12: astore_1 > 13: aload_1 > 14: areturn > 15: getstatic <Field erjang.ERT.NIL erjang.ENil> > 18: dup > 19: nop > 20: astore 5 > 22: dup > 23: nop > 24: astore 6 > 26: dup > 27: nop > 28: astore 7 > 30: nop > 31: astore 8 > 33: aload_1 > 34: invokevirtual <Method erjang.EObject.dec ()erjang.EObject> > 37: astore 4 > 39: aload_1 > 40: astore 5 > 42: aload 4 > 44: astore_1 > 45: aload_3 > 46: astore 7 > 48: aload_2 > 49: astore 6 > 51: aload_0 > 52: aload_1 > 53: aload_2 > 54: aload_3 > 55: invokestatic <Method erjang.m.bench_tak.bench_tak.tak__3 > (erjang.EProc,erjang.EObject,erjang.EObject,erjang.EObject)erjang.EObject> > 58: astore_1 > 59: aload 6 > 61: invokevirtual <Method erjang.EObject.dec ()erjang.EObject> > 64: astore_2 > 65: aload_1 > 66: astore 8 > 68: aload 5 > 70: astore_3 > 71: aload_2 > 72: astore_1 > 73: aload 7 > 75: astore_2 > 76: aload_0 > 77: aload_1 > 78: aload_2 > 79: aload_3 > 80: invokestatic <Method erjang.m.bench_tak.bench_tak.tak__3 > (erjang.EProc,erjang.EObject,erjang.EObject,erjang.EObject)erjang.EObject> > 83: astore_1 > 84: aload 7 > 86: invokevirtual <Method erjang.EObject.dec ()erjang.EObject> > 89: astore_2 > 90: aload_1 > 91: astore 4 93: aload 6 > 95: astore_3 > 96: aload_2 > 97: astore_1 > 98: aload 5 > 100: astore_2 > 101: aload 4 > 103: astore 5 > 105: getstatic <Field erjang.ERT.NIL erjang.ENil> > 108: astore 7 > 110: getstatic <Field erjang.ERT.NIL erjang.ENil> > 113: astore 6 > 115: aload_0 > 116: aload_1 > 117: aload_2 > 118: aload_3 > 119: invokestatic <Method erjang.m.bench_tak.bench_tak.tak__3 > (erjang.EProc,erjang.EObject,erjang.EObject,erjang.EObject)erjang.EObject> > 122: astore_1 > 123: aload 5 > 125: astore_2 > 126: aload_1 > 127: astore_3 > 128: aload 8 > 130: astore_1 > 131: aload_0 > 132: invokevirtual <Method erjang.EProc.check_exit ()void> > 135: goto 3 > > Here's the JAD'ed version of the same code. > > public static EObject tak__3(EProc eproc, EObject eobject, EObject > eobject1, EObject eobject2) > { > do > { > if(eobject1.is_ge(eobject)) > { > eobject = eobject2; > return eobject; > } > EObject obj; > EObject obj1; > EObject obj2; > EObject obj3 = obj2 = obj1 = obj = ERT.NIL; > EObject eobject3 = eobject.dec(); > obj = eobject; > eobject = eobject3; > obj2 = eobject2; > obj1 = eobject1; > eobject = tak__3(eproc, eobject, eobject1, eobject2); > eobject1 = obj1.dec(); > obj3 = eobject; > eobject2 = obj; > eobject = eobject1; > eobject1 = obj2; > eobject = tak__3(eproc, eobject, eobject1, eobject2); > eobject1 = obj2.dec(); > eobject3 = eobject; > eobject2 = obj1; > eobject = eobject1; > eobject1 = obj; > obj = eobject3; > obj2 = ERT.NIL; > obj1 = ERT.NIL; > eobject = tak__3(eproc, eobject, eobject1, eobject2); > eobject1 = obj; > eobject2 = eobject; > eobject = obj3; > eproc.check_exit(); > } while(true); > } > > -- > You received this message because you are subscribed to the Google Groups > "JVM Languages" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/jvm-languages?hl=en. > > -- You received this message because you are subscribed to the Google Groups "JVM Languages" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/jvm-languages?hl=en.
