[parenscript-devel] A simpler way to do multiple value return? (Was: PS test failures in 7be9b45)

Vladimir Sedach vsedach at gmail.com
Wed Sep 12 07:12:59 UTC 2012

> In any case, interoperability with non-PS programs is a separate
> issue- as far as I can tell, neither the GV nor foo.mv designs can
> achieve it.

With the function object approach, JS functions will always return
exactly one value. IMO, having them pass through multiple values would
be the wrong thing.

>> I see a problem in that you'd have to instrument not just return
>> statments, but any kind of control flow that goes up the stack - so
>> you'd have to put the suppression code at the end of every function
>> definition, and also wrap throws.
> I haven't come up with any examples of this yet and would like to see
> one. It seems the question is, how might the GV design fail to clean
> up dangling MV state? There are three ways for MV state to flow in GV:
>   (1) non-tail calls that clear MV;
>   (2) non-tail calls that bind MV and then clear it;
>   (3) tail calls that let MV pass through.

Other exit points from a function are throws and control reaching the
end of the function. So both are going to have to get instrumented.

> It's worth noting that foo.mv might have a problem with errors too:
>   foo.mv = arguments.callee.mv;
>   var result = foo();
>   delete foo.mv;
>   return result;
> If foo() throws an error, there is a dangling foo.mv. Might that be
> harmless? If it isn't, you need something like:
>   foo.mv = arguments.callee.mv;
>   try {
>     return foo();
>   } finally {
>     delete foo.mv;
>   }
> ... around every tail call in the program. The possible performance
> hit is worrisome. That's on top of the possible performance hit of
> arguments.callee.mv, which is the kind of thing that causes V8 to turn
> off optimizations.

Yeah, I just finished up coding the function object approach, and the
generated code gets ugly.

I don't see a way around instrumenting tail calls if you want to
implement multiple value pass-through correctly.

I do see a way to combine the global variable and function object
approach to simplify things:

Since there's only one way the values can travel up the stack, we can
use a single global variable to store the multiple values with the
function object that returned them. That way multiple-value-bind can
check the array, and if it has values from any but the expected
function object, we can just ignore them. To pass through multiple
values, every tail call now has to check the global variable to see if
multiple values got returned by the tail function. If so, it just
replaces the function object they're tagged with with itself.

I can see that approach failing for a recursive function that sets
multiple values in one of its sub-invocations, but doesn't return
multiple values to whoever originally called it expecting multiple


More information about the parenscript-devel mailing list