From: "James Keenan via RT" <[EMAIL PROTECTED]> Date: Sun, 16 Mar 2008 10:46:15 -0700
On Sun Mar 16 10:02:32 2008, rgrjr wrote: > I think it ought to happen, though I think Allison just wanted a ticket > for updating existing PDDs, and not for a whole new PDD. I asked > Allison for a clarification on 11-Mar in Will's "[oops; continuation > 0xb6926320 of type 22 is trying to jump from runloop 15008 to runloop > 1]" thread, and had been waiting for that. > > But I do agree that it ought to be a separate ticket. The underlying > issue is still with us, but has outgrown the original ticket. > Okay. I will now close this ticket. For more granular tracking, I recommend that a separate RT be opened for each existing PDD which needs updating. Thank you very much. kid51 OK, I've finished the writeup for one or more new tickets; please advise on whether this is on target, and how to file it. My personal recommendation is for a single design/documentation ticket, the satisfaction of which will generate a number of implementation tickets. FWIW, the issue seems much less scary for having written it up. It probably also helps that I've let go of the notion that we can ever remove all continuation barriers; it's a big job, and I still can't think of a compelling use case for needing to do so. -- Bob
In between instructions, all Parrot control and data state is captured in Parrot runtime data structures. During the execution of an instruction, some state may be kept temporarily in the C calling stack. If the C code happens to enter an inferior runloop, e.g. to run a vtable method, and that code creates a continuation, this continuation has no way to capture the extra C program state for the partially-executed instruction. If such a continuation were used to resume the inferior runloop after returning to the main one [1], the resumed PIR would execute normally, but when it returned, the latter half of the partial instruction would be skipped. This is a relatively obscure case, but would likely result in a serious failure if the partial instruction was expected to set registers. Coroutines are similarly affected, though it seems strange to want to yield or resume a coroutine from within a vtable method. On the other hand, a coroutine can be thought of as just an application of continuations, so users have a right to expect this to work. The continuation barrier issue is separable into a handful of subproblems, and could be addressed in stages. The topic of this issue, therefore, is to research and document the desired long-term solution to the overall problem, in such PDDs as are appropriate, before starting down the garden path. As a guideline, here is an outline of the subproblems: 1. Currently, it is not even possible to jump from the current inferior runloop to another currently-executing runloop. (The destination runloop in this case belongs to an outer dynamic scope, so this is equivalent to transfer of control to a still-active outer frame in a stack-based implementation.) This "outward continuation" case is commonly encountered in error handling and control structure implementations. The current implementation just runs the new PIR code in the current runloop (after printing a warning), which is almost certainly the wrong thing. In order to fix it, it is only necessary to record a separate longjmp address for each runloop, storing it in a place where Continuation:invoke can use it (after testing that it is still valid!). The original runloop (plus any intervening runloops) would need to be marked as invalid, as their portion of the C stack is being unwound. Languages without continuations or coroutines would need nothing more, so fixing at least this much would help in most cases. 2. Attempts to re-enter a non-existent runloop could be made to work transparently for operations which have limited side effects and return the same result when re-run. For example, most get_integer or store_pmc_indexed_int implementations should fit that description (but obviously not push_pmc). To do this, the code that sets up the inferior runloop can create a return continuation that *restarts* the interrupted instruction. If the return continuation is invoked when its runloop still exists, then that runloop exits normally; otherwise, we stay in the same runloop and return to the instruction that got us into that mess in the first place. 3. Bugs will then be reported for instructions that cannot be restarted this way. It may be possible to fix at least some of them by reordering vtable method calls so that the ones that are expected to have nontrivial side effects are done last. In any case, such bugs should be relatively rare. 4. That leaves a hard-core residue of cases that cannot be fixed without rewriting to eliminate the inferior runloop. At a minimum, this requires adding support for calling a C "continuation" when the PIR returns, and rewriting the C in explicit continuation-passing style, which is a major job. This job could conceivably be made easier by implementing a higher-level unification of C functions, PIR subs, and instruction C code [2]; that's an even bigger job, but has other benefits. Notes: [1] Not currently possible, but assume that subproblem 1 has been addressed. [2] Such as Leo's Cfunc.pod proposal made in http://groups.google.com/group/perl.perl6.internals/msg/09b910b34f6d27f4; see http://groups.google.com/group/perl.perl6.internals/browse_thread/thread/9693de802d3178f3/f298d47bf4df7948 for the complete thread.