I have a question about Vladimir's proposal upthread (from Aug 30) for
passing implicit mv arrays. The idea is to pass MV by setting FOO.MV
before calling FOO, and to read MV passed to oneself as
ARGUMENTS.CALLEE.MV.

As we've been discussing, correct MVR must: (1) enable passthrough
where it's wanted, and (2) suppress passthrough where it's not wanted.
This proposal gets (1) by instrumenting code to pass MV everywhere it
might be needed, and (2) by simply not instrumenting where it isn't
wanted [*]. Here's Vladimir's original example (with comment edited):

  (defun foo (x y z)
    (values x y z))

  (defun bar ()
    (foo)
    (foo))

  function bar () {
    foo(); // no instrumentation since passthrough is not wanted
    foo.mv = arguments.callee.mv;
    var result = foo();
    delete foo.mv;
    return result;
  }

But passthrough is transitive, so we can't just instrument tail calls
to FOO [**]. We also have to instrument tail calls to things that tail
call FOO, like BAZ here:

  (defun foo (x y z)
    (values x y z))

  (defun baz ()
    (foo))

  (defun bar ()
    (foo)
    (baz))

Given this transitivity, how do you distinguish which tail calls are
potentially-multi-valued in order to instrument them? Keep in mind
that passthrough also has to work in cases like:

  (defun baz2 (fn)
    (apply fn '(1 2 3))

  (defun baz3 ()
    (funcall *fn* 1 2 3))

... whenever the calls to FN and *FN* are potentially-multi-valued.

The only easy implementation I can think of is to mv-instrument every
tail call in the program, but that is surely overkill.

Daniel

[*] There's also the recursive case we've been discussing, where you
might both want the instrumentation and not want it -- but since my
question doesn't depend on that complication, let's just ignore it here.

[**] Just to be clear, all I mean by "tail call" is any expression
"(return (some-function))" once PS is done adding in all the implicit
returns.