From: Leopold Toetsch <[EMAIL PROTECTED]>
   Date: Wed, 9 Aug 2006 14:00:19 +0200

   The continuation barrier is only one nastyness of inferior runloops. The 
   second problem with it is that it heavily influences the guts of garbage 
   collection . . .

   See "Method Overloading and GC Issues" in Cfunc.pod. The only way
   IMHO to avoid this problem is to run GC at "safe" points at the
   runloop level . . .

Had you considered keeping track of object references from C variables
explicitly?  This is what Emacs does, and the overhead is surprisingly
low -- less than one line in 300.  There are occasional bugs introduced
due to failure to "GCPRO" the right things at the right times, but the
cost might be more acceptable than conservative GC.  (But, IIUC, your
Csub proposal should make this problem completely avoidable, so this is
just academic curiosity.)

   . . . But the code splitting can be simplifed vastly IMHO. Your POC
   is creating an extra layer between opcodes and C code, which is
   basically doing two things:

   - manage to call user code on behalf of the C code and pass args to it:
     C<Parrot_op_set_reg_from_vtable> and C< C_continuation > stuff
   - pass return results back to the opcode:
     C<store_tail_result_into_register>

Yes.

   The proposal below is dealing with these issues directly in the runloop. 
   Basically all C code is called like this:

       if (info->op_func(interpreter, args)) {
           /* if it branched, goto new pc */
           pc = args[n - 1];
       }

   where C<op_func> is any C function following this calling convention
   . . .

Yes; your proposal clearly goes farther, addressing more problems by
taking a larger view.  And, at least as importantly, it is much less
ugly than the code I wrote.

   When now this opcode function is overloaded, it would be a stub that
   - invokes the PASM/PIR subroutine, which returns the new C<pc>
     and creates a return continuation
   - sets up current_args and current_results pointers
   Then the runloop would just dispatch to the PASM/PIR user code and run it 
w/o 
   any inferior runloop.

   There's still the mentioned problem of calling user code deeply inside some 
   called C function. E.g. calling C<get_string> from with C<parrot_pass_args> 
   due to argument conversion. This can be handled by a combination of:

   a) roll it into the runloop e.g.
      print_p  => set_s_p ; print_s
   b) disallow or restrict some overloading
   c) handle argument conversion at the runloop too

We still need a mechanism to run C when the PASM/PIR sub returns,
though.  In the case of (e.g.) rewinding the stack, you need a hook to
tell Continuation:invoke to resume rewinding [1].

   . . .

   The attached Cfunc.pod has plenty other reasons, why we might need to
   change C internals as well. The continuation barrier is just one of
   these.

   Comments welcome,
   leo

I have mostly questions, but these are about details; I'd rather see
others respond first.

   There is one pressing question, though:  I had intended to use the
continuation-tailcalling mechanism from the POC to eliminate inferior
runloops from stack rewinding, as the logical next step in my campaign
to clean up dynamic environment support.  Should I wait for a more
complete Cfunc.pod design, or should I proceed in the expectation that
the continuation-tailcalling mechanism isn't likely to change that much?

                                        -- Bob

[1]  Of course, that can be done in terms of a Csub, but you still need
     the equivalent of C_closure state.

Reply via email to