On Apr 29, 2011, at 6:19 AM, Rémi Forax wrote:

> ricochet rulez ?
> 
> Rémi

Haz ricochet.

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.

-- John
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to