On Nov 10, 2004, at 11:53 PM, Leopold Toetsch wrote:

Jeff Clites <[EMAIL PROTECTED]> wrote:

...it sounds like we have an easy way to tell if a "real" continuation
has a claim on the register frame, because creating such a real
continuation can mark the frame,

There is no such mark. If ctx->current_cont isa(RetContinuation), then it's save to do the tail call.

Good--implicit mark then.

This OTOH is meaning that we can do the
check only at runtime. Thus the C<tailcall> or C<tailcallmethod> opcodes
have to do plain calls if they detect such a situation.

Yep, although there will be some situations where we can know for sure at compile time--for instance if all function calls within a function are tail calls. (We could have a special sort of C<tailcalldontcheck>, but that depends on our philosophy--if it's okay for the VM to trust the compiler. Or possibly the VM could detect this, and cache this information as a sort of dynamic optimization; or a bytecode verifier could ensure that C<tailcalldontcheck> is valid in a given context. Multiple options here.)


And also, even when C<tailcall> has to fall back to a plain call, it doesn't have to fall all the way back--it can still pass along the return continuation from its caller, and get some benefit.

... (In fact that mark should be a reference
count,

That's really not needed. If you return from the function and you call it next time, you've again a RetContinuation. If the continuation was created somewhere deeper in the call chain, it's gone or not after the GC cycle.

But if ctx->current_cont has been promoted to a real continuation (as a result of something that happened deeper in the stack), it will never be turned back to a RetContinuation, even if it could have been (ie, if GC reclaimed the things that caused the promotion), so we might forego a tail call that we could have made.


And you know - starting with refcounting one objects ends up
with refcounting containers holding that item ...

Not really. In this case, the only things which are allowed to point to a register frame (via a ctx) are the interpreter itself, and continuations. There are just a couple of specific points where the ref count would need to be incremented/decremented (including the destroy() of continuations). But that's the clear place to stop--you don't need to ref count the continuations themselves, since that wouldn't be practical (you'd need write barriers to always check if you're referencing or un-referencing a continuation, etc.). We wouldn't have to go off the deep end with it.


JEff



Reply via email to