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?