Dan~
On Tue, 30 Nov 2004 09:49:54 -0500, Dan Sugalski <[EMAIL PROTECTED]> wrote:At 9:36 AM -0500 11/30/04, Matt Fowles wrote:
>Dan~
>
>
>On Tue, 30 Nov 2004 08:28:35 -0500, Dan Sugalski <[EMAIL PROTECTED]> wrote:
>> At 1:45 AM -0800 11/29/04, Jeff Clites wrote:
>>
>>
>> >On Nov 28, 2004, at 2:48 AM, Piers Cawley wrote:
>> >
>> >>I just thought of a heuristic that might help with register
>> >>preservation:
>> >>
>> >>A variable/register should be preserved over a function call if
>>either of the
>> >>following is true:
>> >>
>> >>1. The variable is referred to again (lexically) after the function has
>> >> returned.
>> >>2. The variable is used as the argument of a function call within the
>> >> current compilation unit.
>> >
>> >That doesn't solve it, though you'd think it would. Here's the
>> >counter-example:
>> >
>> > x = 1
>> > foo()
>> > print x
>> > y = 2
>> > return y
>> >
>> >You'd think that x and y could use the same memory location
>> >(register, variable--whatever), since ostensibly their lifetimes
>> >don't overlap. But continuation re-invocation can cause foo() to
>> >return multiple times, and each time it should print "1", but it
>> >won't if x and y use the same "slot" (it would print "2" each time
>> >after the first). In truth, their lifetimes do overlap, due to the
>> >hidden (potential) loops created by continuations.
>>
>> Except... we've already declared that return continuations are
>> special, and preserve the registers in the 16-31 range. So when we
>> return from foo, regardless of how or how many times, the pointer to
>> x's PMC will be in a register if it was in there before the call to
>> foo, if it's in the preserved range. So in this case there's no
>> problem. Things'll look like:
>>
>> x = 1 # new P16, .Integer; P16 = 1 # P16 has pointer value 0x04
>> foo() # foo invocation
>> print x # P16 still has pointer value 0x04
>> y = 2 # new P16, .Integer; P16 = 2 # P16 now has pointer value 0x08
>> return y # Passes back 0x08
>>
>> With more or less clarity.
>
>I think that the concern is for the circumstance where foo() promotes
>it return continuation to a full continuation. Then, that guarantee
>is no longer provided (I think), and repeated invocation could leave y
>in P16 rather than x.
Nope. The guarantee's still there. Promotion will force things up the call chain to get marked as un-recyclable, but registers still get restored on invocation.
In that case, I am confused. When does the guarantee NOT apply?
When a general-purpose continuation's taken. Return continuations are special case, designed to make sub calls and returns work as people expect in the face of the underlying CPS mechanism we have. (They are, if you like, a cheat) Exception continuations are also special-case continuations. As are sub and method PMCs when you get right down to it.
A general purpose continuation has two things attached to it. The first is a destination address -- where in the code to go when the continuation is invoked. The second thing attached is an environment -- the lexical pad pointer, namespace pointer, opcode library pointer, security information, top stack frame pointers, and so on. Basically everything in the interpreter structure outside of the internal bookkeeping and interpreter global information. (The context structure's misnamed. It's not the context that continuations care about)
When a continuation (or, really, anything) is invoked, parts of the interpreter struct are overwritten with information from the continuation, parts are left alone, and parts are effectively nulled out. Which bits do what depends entirely on the continuation/invokable, as each type saves/ignores/nulls different things.
--
Dan
--------------------------------------it's like this------------------- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk