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.

 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.

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

leo

Reply via email to