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

yield op?

6 views
Skip to first unread message

Michal Wallace

unread,
Jan 9, 2004, 3:29:49 AM1/9/04
to perl6-i...@perl.org

Hey all,

When you invoke a Coroutine, it calls swap_context()
from src/sub.c ... There's an else clause in there
that either swaps or restores theinterpreter stack,
but as far as I can tell, swap_context() is ONLY
called when entering a coroutine - not when we're
suspending it. That means all sorts of nasty things
happen when the either coroutine or the calling
context gets modified.

For example, the code below counts up from 1 to
forever. But if you uncomment the zero=0 line,
it never gets higher than 1 because "zero"
in __main__ and "x" in "_iterator" get assigned
to the same register, and the context isn't
properly restored.

It seems to me that invoke() is doing the right
thing by swapping the context, but that there
needs to be a yield() method (and opcode?) to
balance it out. It definitely needs more than
a savetop or an "invoke" of ther return
continuation, because neither of these things
would let you fire a method on the coroutine
instance. That's why I'm thinking we need a
yield op.

Am I on the right track here? Either way,
what can I do to get this working?

Sincerely,

Michal J Wallace
Sabren Enterprises, Inc.
-------------------------------------
contact: mic...@sabren.com
hosting: http://www.cornerhost.com/
my site: http://www.withoutane.com/
--------------------------------------

#!/bin/env parrot
# uncomment the second zero=0 line to see the magic bug :)

.sub __main__
.local Coroutine itr
.local object return
.local object counter
newsub itr, .Coroutine, _iterator

.local object zero
zero = new PerlInt
zero = 0

newsub return, .Coroutine, return_here
loop:
.pcc_begin non_prototyped
.pcc_call itr, return
return_here:
.result counter
.pcc_end

print counter
print " "

### zero = 0
print zero
print "\n"
goto loop
end
.end


.pcc_sub _iterator non_prototyped
.local object x
x = new PerlInt
x = 0
iloop:
.pcc_begin_yield
.return x
.pcc_end_yield
x = x + 1
goto iloop
.end


Leopold Toetsch

unread,
Jan 9, 2004, 3:47:37 AM1/9/04
to Michal Wallace, perl6-i...@perl.org
Michal Wallace <mic...@sabren.com> wrote:

> Hey all,

> When you invoke a Coroutine, it calls swap_context()

Can you have a look at imcc/t/syn/pcc.t, there is an coroutine iterator
test.

leo

Michal Wallace

unread,
Jan 9, 2004, 11:23:42 PM1/9/04
to Leopold Toetsch, perl6-i...@perl.org

Yep, it has the same problem. The patch below exposes it.
Comment out the first zero=0 line and you get an infinite
stream of sixes. With both in there it prints two numbers
and ends. (This is without Luke's patch)

The principle seems to be that you can't modify anything
in the context without screwing up the continuation's
registers.

Sincerely,

Michal J Wallace
Sabren Enterprises, Inc.
-------------------------------------
contact: mic...@sabren.com
hosting: http://www.cornerhost.com/
my site: http://www.withoutane.com/
--------------------------------------


Index: t/syn/pcc.t
===================================================================
RCS file: /cvs/public/parrot/imcc/t/syn/pcc.t,v
retrieving revision 1.28
diff -u -r1.28 pcc.t
--- t/syn/pcc.t 16 Dec 2003 08:53:44 -0000 1.28
+++ t/syn/pcc.t 10 Jan 2004 03:41:28 -0000
@@ -489,6 +489,8 @@

output_is(<<'CODE', <<'OUT', "coroutine iterator");
.sub _main
+ .local int zero
+ zero=0
.local int i
i=5
newsub $P0, .Coroutine, _addtwo
@@ -500,6 +502,7 @@
ret_addr:
.result $I2
.pcc_end
+ zero = 0
print $I2
print "\n"
savetop

Leopold Toetsch

unread,
Jan 11, 2004, 9:24:55 AM1/11/04
to Michal Wallace, perl6-i...@perl.org, d...@sidhe.org
Michal Wallace <mic...@sabren.com> wrote:

> Hey all,

> When you invoke a Coroutine, it calls swap_context()
> from src/sub.c ... There's an else clause in there
> that either swaps or restores theinterpreter stack,
> but as far as I can tell, swap_context() is ONLY
> called when entering a coroutine - not when we're
> suspending it.

No, swap_context() is called for each invoke of the Coroutine, that is
ok. But (as with Continuations) the register frame stacks are *not*
swapped. So the "zero" in your example (in P16) is shared between the
Coroutine and main.

If no one hollers, I'll apply Luke's patch WRT register stacks and
Continuations and then fix Coroutines.

leo

Michal Wallace

unread,
Jan 11, 2004, 2:02:30 PM1/11/04
to Leopold Toetsch, perl6-i...@perl.org
On Sun, 11 Jan 2004, Leopold Toetsch wrote:

> Michal Wallace <mic...@sabren.com> wrote:

> > When you invoke a Coroutine, it calls swap_context()
> > from src/sub.c ... There's an else clause in there
> > that either swaps or restores theinterpreter stack,
> > but as far as I can tell, swap_context() is ONLY
> > called when entering a coroutine - not when we're
> > suspending it.
>
> No, swap_context() is called for each invoke of the Coroutine, that is
> ok. But (as with Continuations) the register frame stacks are *not*
> swapped. So the "zero" in your example (in P16) is shared between the
> Coroutine and main.

Yes, that's what I meant. It's called each time you invoke
the coroutine. I don't understand why it doesn't have to be
swapped back each time you suspend the coroutine.

But then again, I tried fixing it myself and it didn't work...
Maybe I'll understand once I see how you fix it.


> If no one hollers, I'll apply Luke's patch WRT register stacks and
> Continuations and then fix Coroutines.

Awesome! Thanks!

Dan Sugalski

unread,
Jan 12, 2004, 11:05:40 AM1/12/04
to Michal Wallace, perl6-i...@perl.org
At 3:29 AM -0500 1/9/04, Michal Wallace wrote:
>It seems to me that invoke() is doing the right
>thing by swapping the context, but that there
>needs to be a yield() method (and opcode?) to
>balance it out.

Yes, there does need to be one, or rather there needs to be something
to refresh a continuation with the current information, since we
don't really have a yield as such.

This brings up some nasty issues with coroutines that we need to
address, so compilers can emit the proper sequence of code to get or
not get a new coroutine as they need.
--
Dan

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

Leopold Toetsch

unread,
Jan 13, 2004, 4:45:03 AM1/13/04
to Michal Wallace, perl6-i...@perl.org
Michal Wallace <mic...@sabren.com> wrote:

> Hey all,

> When you invoke a Coroutine, it calls swap_context()

Register frames are now properly swapped too. Your given example is
working now. I've checked in a slightly modified version as a test.

leo

0 new messages