Leopold Toetsch <[EMAIL PROTECTED]> writes:

> Piers Cawley <[EMAIL PROTECTED]> wrote:
>
>> Further to my last response. If you have things set up so that you can
>> return multiple times from the same function invocation then the return
>> continuation should have been replaced with a full continuation before
>> the first return, so even the first return will use copying semantics,
>> and the registers will always be restored to the state they were in when
>> the function was first called, which is absolutely the right thing to
>> do.
>
> Here is again the example I've brought recently. Please go through it
> and tell me what's wrong with my conclusion.
>
>
>    $I0 = 42             # set I16, 42                 42
>    $N0 = 2.5            # set N16, 2.5                ..101...
>    $S0 = "a"            # set S16, "a"                0x1004  -> "a"
>    $P0 = "a"            # set P16, "a"                0x2008  -> "a"
>   loop:
>    foo()                # set P0, ...; invokecc
>
>  We have some temporary variables and a function call. Variables are used
>  beyond that point, so the register allocator puts these in the preserved
>  register range. The function C<foo()> might or might not capture the
>  continuation created by the C<invokecc> opcode.
>
>  Let's assume, it is captured, and stored into a global, if it wasn't
>  already, i.e. the first time. According to Dan's plan, the function
>  return restores the register contents to the state of the creation of
>  the return continuation, which is shown in the right column.
>
>    $I0 += 1             # add I16, 1                  43
>    $N0 *= 2.0           # mul N16, 2.0                .101....
>    $S0 .= "b"           # concat S16, "b"             0x1008  -> "ab"
>    inc $P0              # inc P16                     0x2008  -> "b"
>    dec a                # dec P17                     0x200c  -> 1
>    if a goto loop       # if P17, loop
>
>  A note WRT strings: the concat might or might not assign a new string to
>  S16. It depends on the capacity of the string buffer. But generally:
>  string operations do create new string headers with a different memory
>  address like shown here. While S registers hold pointers, they have
>  value semantics.

Is that guaranteed? Because it probably needs to be.

>
>  Now we loop once over the function call. This creates a new return
>  continuation and on function return registers are restored to their new
>  values (44, 10.0, "abb", "c"). All fine till here.
>
>  The loop counter "a" reaches zero. Now the next instruction is
>  another function call.
>
>    bar()                # set P0, ... invokecc
>
>  The "bar()" function extracts the return continuation captured in the
>  first call to "foo()" from the global and invokes it. Control flow
>  continues right after the "invokecc" opcode that called "foo()".
>
>  This would restore the register contents to the first state shown above.
>  That is, not only I and N registers would be clobbered also S registers
>  are involved.

That's correct. What's the problem? Okay, you've created an infinite
loop, but what you're describing is absolutely the correct behaviour for
a continuation. If you need any state to be 'protected' from taking the
continuation then it needs to be in a lexical or a mutated PMC. This is
just how continuations are supposed to work. 

>  Above code could only use P registers. Or in other words: I, N, and S
>  registers are almost[1] useless.

No they're not. But you should expect them to be reset if you take a
(full) continuation back to them. 

Presumably if foo() doesn't store a full continuation, the restoration
just reuses an existing register frame and, if foo has made a full
continuation its return does a restore by copying?

Reply via email to