hg: mlvm/mlvm/jdk: 2 new changesets
john.r.rose at oracle.com
Fri Apr 29 14:36:56 PDT 2011
On Apr 29, 2011, at 6:19 AM, Rémi Forax wrote:
> ricochet rulez ?
Here are some comments on this stuff.
Curry's original BCKW system of combinators (http://en.wikipedia.org/wiki/B,C,K,W_system) is similar to the MH api.
B(f,g) = λ x . f(g(x)) // MHs.filterArguments(f, 0, g)
K(x) = λ _ . x // MHs.constant(x)
C(f) = λ x,y . f(y,x) // MHs.permuteArguments(f, 1,0)
W(f) = λ x . f(x,x) // MHs.permuteArguments(f, 0,0)
The ricochet frame implements B, which must pause the execution of the whole method handle (h(u)=B(f,g)(u)) to execute user code (v=g(u)) before calling the component method handle f (f(v)).
It's called a ricochet because, from the JVM's view point, two method handle invocations g(x) and f(y) must be launched in succession. The stack frame redirects control flow from the return of y=g(x) returns to the call f(y). That latter call is a tail-call, so the frame disappears. Its job in life it to "bounce" y=g(x) over to f(y). Any further computation is totally determined by f.
The "frame-ness" of the ricochet frame is minimal, just enough to manage the bounce, and to protect any values needed for the second call.
The behavior of a ricochet frame is in one of two general forms:
COLLECT(f,g) = λ k1*,c*,k2* . f(k1*,g(c*),k2*)
FOLD(f,g) = λ k1*,c*,k2* . f(k1*,g(c*),c*,k2*)
The stars mark sequences of arguments (any number 0<=N<=255) of any type. Void return values are treated as zero-tuples. Internally, longs and doubles are treated as pairs of arguments. The only difference between COLLECT and FOLD is whether the c arguments are retained for f. Filtering a single argument (or boxing a primitive) is simply a 1-argument COLLECT.
Degrees of freedom are:
- the types of f and g (totally polymorphic)
- division of incoming arguments (k1,k2 are "kept" for f, while c are "collected" by g)
- whether the collected arguments are retained for f (fold vs. filter)
- the return type of g (float, ref, int, void)
The return type of g affects the mechanics of how it y=g(x) is folded into the final argument list f(u). The frame code itself manages this simply, by pre-formatting the saved arguments for the eventual call to f, but leaving a "hole" of one or two stack slots for the return value. The frame then contains an index telling its return continuation where to store the returned value. At that point, the frame pops and f(u) executes as if g(x) had never happened.
Ricochet frames handle boxing and varargs collection (which might call the GC), filterArguments, filterReturnArgument, foldArguments, and a bunch of internal stuff.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the mlvm-dev