Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

towards a new call scheme

16 views
Skip to first unread message

Leopold Toetsch

unread,
Sep 23, 2004, 10:15:26 AM9/23/04
to P6I
I've started tweaking internals to get a faster calling scheme in place.
Part 1 (in CVS) moved the subroutine's address into the parrot_sub_t
structure. Accessing such Sub-internals via get_pointer & set_pointer is
working still safely.

Anyway, next will be to hide the return continuation in the interpreter
context. So we need to have some opcodes to access the return
continuation, e.g.:

get_cc(OUT Px) # 1) get current continuation, i.e. the return cont.
return_cc() # 2) return via current continuation

1) is only needed for special porposes, like passing the continuation on
to a different place. The normal way to return from a sub will be 2)

If that's in, access to C<P1> as a return continuation will be deprecated.

The PIR sequence:

.pcc_begin_return
.return foo
.pcc_end_return

will do the right thing accordingly.

Accompanied with that change, we could need another new opcode:

get_sub(OUT Px) # get current Sub PMC

Having the current Sub in the C<P0> register isn't really safe, as user
code always can reuse that register. But we want to have error
trackbacks finally, which will need to climb up the call chain in a safe
way. Currently C<P0> as well as C<P1> might be saved away by C<pushp> or
similar and live somewhere in the register backing stack only.

Any thoughts?
leo

Dan Sugalski

unread,
Sep 23, 2004, 1:16:56 PM9/23/04
to Leopold Toetsch, P6I
At 4:15 PM +0200 9/23/04, Leopold Toetsch wrote:
>I've started tweaking internals to get a faster calling scheme in
>place. Part 1 (in CVS) moved the subroutine's address into the
>parrot_sub_t structure. Accessing such Sub-internals via get_pointer
>& set_pointer is working still safely.
>
>Anyway, next will be to hide the return continuation in the
>interpreter context. So we need to have some opcodes to access the
>return continuation, e.g.:
>
> get_cc(OUT Px) # 1) get current continuation, i.e. the return cont.

In a rare, possibly unique burts of opcode parsimoniousness...
perhaps this would be a good thing for the interpinfo op. It returns
current interpreter info, and the current return continuation would
be a good one to do, as would the current object and current
sub/method PMC. (As well as the current namespace root, current
lexical pad root...)

> return_cc() # 2) return via current continuation
>
>1) is only needed for special porposes, like passing the
>continuation on to a different place. The normal way to return from
>a sub will be 2)
>
>If that's in, access to C<P1> as a return continuation will be deprecated.

Well... should we? We're still passing the return continuation *in*
in P1, unless you want to move it out and unconditionally make it a
parameter to invoke. Which is OK, but we should be up front.

>The PIR sequence:
>
> .pcc_begin_return
> .return foo
> .pcc_end_return
>
>will do the right thing accordingly.

I think I'd also like to make a change to sub invocation, too, to
allow passing in alternate return continuations, which makes tail
calls easy. At this point I'm not inclined to have any special tail
call support built into parrot because it's just not needed, but IMCC
support is still handy.

A .returncont arg to the long-form sub call would work fine. If we
want to have a variant short-form to support it that'd be fine.
--
Dan

--------------------------------------it's like this-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Luke Palmer

unread,
Sep 23, 2004, 1:23:05 PM9/23/04
to Dan Sugalski, Leopold Toetsch, P6I
Dan Sugalski writes:
> At 4:15 PM +0200 9/23/04, Leopold Toetsch wrote:
> > return_cc() # 2) return via current continuation
> >
> >1) is only needed for special porposes, like passing the
> >continuation on to a different place. The normal way to return from
> >a sub will be 2)
> >
> >If that's in, access to C<P1> as a return continuation will be deprecated.
>
> Well... should we? We're still passing the return continuation *in*
> in P1, unless you want to move it out and unconditionally make it a
> parameter to invoke. Which is OK, but we should be up front.

What we'd really like is to get the call chain. That is, given a
continuation, can we query it to see what the previous continuation was?

Luke

Dan Sugalski

unread,
Sep 23, 2004, 1:25:44 PM9/23/04
to Luke Palmer, Leopold Toetsch, P6I

Yes. All the information in the continuation is inspectable. (And the
interpreter needs to do this for exceptions, for example) Not
directly modifiable (I think) but inspectable.

Piers Cawley

unread,
Sep 24, 2004, 2:52:32 AM9/24/04
to Leopold Toetsch, Dan Sugalski, P6I
Leopold Toetsch <l...@toetsch.at> writes:

> Dan Sugalski wrote:
>
>> At 4:15 PM +0200 9/23/04, Leopold Toetsch wrote:
>>> get_cc(OUT Px) # 1) get current continuation, i.e. the return cont.
>> In a rare, possibly unique burts of opcode parsimoniousness... perhaps
>> this would be a good thing for the interpinfo op.
>

> That's fine too.


>
>
>>> return_cc() # 2) return via current continuation
>>>
>>> 1) is only needed for special porposes, like passing the continuation
>>> on to a different place. The normal way to return from a sub will be
>>> 2)
>>>
>>> If that's in, access to C<P1> as a return continuation will be
>>> deprecated.
>> Well... should we? We're still passing the return continuation *in* in
>> P1, unless you want to move it out and unconditionally make it a
>> parameter to invoke.
>

> Well, basically, if an interpreter template is used (hanging off the
> subroutine), the previous interpreter template is the return
> continuation. That means that for the usual case (function call and
> return) there isn't any need to construct a return continuation and put
> it somewhere. The return continuation would only be needed to create a
> real continuation out of it and pass it along somewhere.
>
> If that calling scheme doesn't fly, its still better to have specific
> locations in the interpreter context that hold the sub and the return
> continuation to allow simple function backtrace for the error case or
> introspection. That's currently not possible, because P0 and P1 can be
> swapped out into the register backing stack and reused to hold something
> totally different.


>
>> I think I'd also like to make a change to sub invocation, too, to
>> allow passing in alternate return continuations, which makes tail
>> calls easy.
>

> Ok. Good point. We could get rid of C<invoke Px> (call the sub in Px w/o
> calling conventions) in favor of C<invoke_with_retc Px>. Anyway, the
> visible part of a return continuation (in above opcode or C<get_cc>
> would be a continuation. The "normal" case (call/return) could just have
> that continuation internally in the context. No additional PMC is
> constructed ifn't needed.

I could be wrong here, but it seems to me that having a special
'tailinvoke' operator which simply reuses the current return
continuation instead of creating a new one would make for rather faster
tail calls than fetching the current continuation out of the interpreter
structure, then invoking the target sub with with this new
continuation (ISTM that doing it this way means you're going to end up
doing a chunk of the work of creating a new return continuation anyway,
which rather defeats the purpose.)

Leopold Toetsch

unread,
Sep 24, 2004, 4:13:50 AM9/24/04
to Piers Cawley, perl6-i...@perl.org
Piers Cawley <pdca...@bofh.org.uk> wrote:

> I could be wrong here, but it seems to me that having a special
> 'tailinvoke' operator which simply reuses the current return
> continuation instead of creating a new one would make for rather faster
> tail calls than fetching the current continuation out of the interpreter
> structure, then invoking the target sub with with this new
> continuation (ISTM that doing it this way means you're going to end up
> doing a chunk of the work of creating a new return continuation anyway,
> which rather defeats the purpose.)

Yep, that's true. We already have (unimplemented) C<tailcallmethod>
opcodes. A plain C<tailcall> for functions is still missing. Anyway, if
the current continuation has its location in the interpreter context,
its simple to implement these opcodes.
If a real continuation object is constructed or not is invisible then
and can be considered as an implementation detail.

Anyway, I think that the current continuation will be mostly invisible
except in code like your backtracking example, where you explicitely
request the (call-with-current-continuation ...).

leo

Jeff Clites

unread,
Sep 25, 2004, 7:03:37 PM9/25/04
to l...@toetsch.at, perl6-i...@perl.org, Piers Cawley
On Sep 24, 2004, at 1:13 AM, Leopold Toetsch wrote:

> Piers Cawley <pdca...@bofh.org.uk> wrote:
>
>> I could be wrong here, but it seems to me that having a special
>> 'tailinvoke' operator which simply reuses the current return
>> continuation instead of creating a new one would make for rather
>> faster
>> tail calls than fetching the current continuation out of the
>> interpreter
>> structure, then invoking the target sub with with this new
>> continuation (ISTM that doing it this way means you're going to end up
>> doing a chunk of the work of creating a new return continuation
>> anyway,
>> which rather defeats the purpose.)
>
> Yep, that's true. We already have (unimplemented) C<tailcallmethod>
> opcodes. A plain C<tailcall> for functions is still missing. Anyway, if
> the current continuation has its location in the interpreter context,
> its simple to implement these opcodes.

You mentioned:

> Well, basically, if an interpreter template is used (hanging off the
> subroutine), the previous interpreter template is the return
> continuation.

So this occurred to me: Not sure if it would be useful, but since you'd
be able to trace back up the call stack, a tailcall for functions
could take a numeric parameter, to let you invoke a continuation from
further back in the stack, without having had to pass it in as an
explicit parameter. So for instance:

return_cc ==> alias for call_cc_indexed 0
tailcall ==> alias for call_cc_indexed 1
call_cc_indexed 2 ==> invoke the continuation from 2 frames back, as
though it had been passed down

It's just a generalization--it lets you do the equivalent of grabbing
the current continuation, and passing that to a function which passes
it to a function which passes it to a function...which invokes it,
without having to ever create a real PMC.

But I'm not sure if that's a useful design pattern.

JEff

Leopold Toetsch

unread,
Sep 26, 2004, 7:18:00 AM9/26/04
to Jeff Clites, perl6-i...@perl.org
Jeff Clites <jcl...@mac.com> wrote:

> return_cc ==> alias for call_cc_indexed 0
> tailcall ==> alias for call_cc_indexed 1
> call_cc_indexed 2 ==> invoke the continuation from 2 frames back, as
> though it had been passed down

Yep. I can imagine that that's avaiable as:

$P0 = interpinfo .INTERPINFO_CALLCHAIN # _TRACEBACK ?
$P1 = $P0[2]
cont = $P1."_current_continuation"()
invoke cont

or some such. I don't think it needs opcode support, though.

> JEff

leo

0 new messages