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

[PATCH] new_noinit and init ops

13 views
Skip to first unread message

Luke Palmer

unread,
Jan 12, 2004, 3:00:06 PM1/12/04
to Internals List
I have somewhat a predicament. I want to create a continuation, and
have that continuation stored in the register stack that it closes over
(this is how I'm implementing a loop with continuations). Unless I'm
having a major braino, I don't think this is possible at the moment.

I got around this by adding two ops: new_noinit and init. I've included
a patch that implements them. Other solutions welcome.

Luke

Index: ops/pmc.ops
===================================================================
RCS file: /cvs/public/parrot/ops/pmc.ops,v
retrieving revision 1.16
diff -u -r1.16 pmc.ops
--- ops/pmc.ops 31 Dec 2003 11:54:38 -0000 1.16
+++ ops/pmc.ops 12 Jan 2004 19:54:45 -0000
@@ -52,6 +52,15 @@
Like above. The forth argument is a property hash - it isn't copied in,
only referended. The initializer may be NULL.

+=item B<new_noinit>(out PMC, in INT)
+
+Just like above, but doesn't initialize the PMC. You must call B<init>
+on it before using it.
+
+=item B<init>(in PMC)
+
+Initializes a PMC created with new_noinit.
+
=cut

op new(out PMC, in INT) {
@@ -60,9 +69,6 @@
abort(); /* Deserve to lose */
}

- /* Why?? If we're creating a continuation, the continuation PMC
- * needs to be in the destination register before its init method
- * copies the registers. */
$1 = pmc_new_noinit(interpreter, $2);
$1->vtable->init(interpreter, $1);
goto NEXT();
@@ -84,6 +90,19 @@
$1->vtable->init_pmc_props(interpreter, $1, $3, $4);
goto NEXT();
}
+# }
+
+op new_noinit(out PMC, in INT) {
+ if ($2 <= 0 || $2 >= enum_class_max) {
+ internal_exception(1, "Illegal PMC enum (%d) in new\n", (int)$2);
+ }
+ $1 = pmc_new_noinit(interpreter, $2);
+ goto NEXT();
+}
+
+op init(in PMC) {
+ $1->vtable->init(interpreter, $1);
+ goto NEXT();
}

########################################

Luke Palmer

unread,
Jan 12, 2004, 3:02:58 PM1/12/04
to Internals List
Luke Palmer writes:
> ...

>
> goto NEXT();
> @@ -84,6 +90,19 @@
> $1->vtable->init_pmc_props(interpreter, $1, $3, $4);
> goto NEXT();
> }
> +# }

^^^^^

Don't mind that. I thought I saw an extra one, and commented it out to
make sure I wasn't being stupid. Wasn't, and forgot to uncomment.

Luke

Dan Sugalski

unread,
Jan 12, 2004, 3:07:13 PM1/12/04
to Luke Palmer, Internals List
At 1:00 PM -0700 1/12/04, Luke Palmer wrote:
>I have somewhat a predicament. I want to create a continuation, and
>have that continuation stored in the register stack that it closes over
>(this is how I'm implementing a loop with continuations).

Erm. I don't think this is the right way to do this. Before I go any
further, though -- you've a reason to not store this PMC in either a
pad slot or the global stash, and just having it in a register is
insufficient?
--
Dan

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

Michal Wallace

unread,
Jan 12, 2004, 3:37:31 PM1/12/04
to Luke Palmer, Internals List
On Mon, 12 Jan 2004, Luke Palmer wrote:

> I have somewhat a predicament. I want to create a continuation, and
> have that continuation stored in the register stack that it closes
> over (this is how I'm implementing a loop with continuations).
> Unless I'm having a major braino, I don't think this is possible at
> the moment.
>
> I got around this by adding two ops: new_noinit and init. I've
> included a patch that implements them. Other solutions welcome.

Hmm. That sounds like Coroutine. Also, when you invoke
any kind of sub with the calling conventions, it's
already in P0. Can't you store that in a local variable
on the invoke?

Sincerely,

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

Luke Palmer

unread,
Jan 12, 2004, 6:24:11 PM1/12/04
to Michal Wallace, Internals List
Michal Wallace writes:
> On Mon, 12 Jan 2004, Luke Palmer wrote:
>
> > I have somewhat a predicament. I want to create a continuation, and
> > have that continuation stored in the register stack that it closes
> > over (this is how I'm implementing a loop with continuations).
> > Unless I'm having a major braino, I don't think this is possible at
> > the moment.
> >
> > I got around this by adding two ops: new_noinit and init. I've
> > included a patch that implements them. Other solutions welcome.
>
> Hmm. That sounds like Coroutine.

Uh, how so? Are we mixing up Continuation/Coroutine vocabulary again?

> Also, when you invoke any kind of sub with the calling conventions,
> it's already in P0. Can't you store that in a local variable on the
> invoke?

Yeah, I wouldn't normally consider it pad material, but that does seem
like the cleanest way at the moment.

Luke

Michal Wallace

unread,
Jan 12, 2004, 8:23:38 PM1/12/04
to Luke Palmer, Internals List
On Mon, 12 Jan 2004, Luke Palmer wrote:

> Michal Wallace writes:
> > On Mon, 12 Jan 2004, Luke Palmer wrote:
> >
> > > I have somewhat a predicament. I want to create a continuation, and
> > > have that continuation stored in the register stack that it closes
> > > over (this is how I'm implementing a loop with continuations).
> >

> > Hmm. That sounds like Coroutine.
>
> Uh, how so? Are we mixing up Continuation/Coroutine vocabulary again?

:)

Well... A Coroutine is a pausable, resumable continuation, right?
Or basically a closure with a continuation inside it. I was just
guessing how you might be implementing the loop. It sounds like
a recursive tail call, but that struck me as a job for goto
instead of a continuation. So I thought maybe you needed the
continuation to save for later, and that made me think of a
Coroutine.

That's what was running through my head anyway. As for
why I mentioned it based on all those assumptions... uhh,
beats me. My real point was just the part about the
calling conventions the thing you're calling in P0. :)

Luke Palmer

unread,
Jan 12, 2004, 8:55:04 PM1/12/04
to Michal Wallace, Internals List
Michal Wallace writes:
> On Mon, 12 Jan 2004, Luke Palmer wrote:
>
> > Michal Wallace writes:
> > > On Mon, 12 Jan 2004, Luke Palmer wrote:
> > >
> > > > I have somewhat a predicament. I want to create a continuation, and
> > > > have that continuation stored in the register stack that it closes
> > > > over (this is how I'm implementing a loop with continuations).
> > >
> > > Hmm. That sounds like Coroutine.
> >
> > Uh, how so? Are we mixing up Continuation/Coroutine vocabulary again?
>
> :)
>
> Well... A Coroutine is a pausable, resumable continuation, right?
> Or basically a closure with a continuation inside it.

Both of those sentences seem wildly redundant to me. I think we might
be stuck on vocabulary. We're surely both understanding the same thing
in different ways.

A continuation is one snapshot -- it never changes, it never runs. To
invoke the continuation is to take you back to that snapshot and start
running from there. To invoke it a second time is exactly like invoking
it the first time.

A coroutine is like a variable that holds continuations, and updates
itself whenever it "yields". I guess that's the best way I can put it
with my affliction against coming up with good similes.

I think this is what you were saying... maybe.

But it's easy to implement a loop using a single continuation. Like
this:

newsub $P0, .Continuation, again
again:
# ... loop body
invoke $P0

That's not *exactly* what I was doing. All I was doing was
implementing a loop that called subs repeatedly with a "backtrack"
continuation, so they could jump out at any point in their execution.
It seemed odd that there was no way to keep the continuation I was
giving everyone around without using a lexical pad.

It's working now (there are some weird things going on though which I'm
trying to track down), and I don't really mind the lexical pad.

Luke

Michal Wallace

unread,
Jan 12, 2004, 11:18:55 PM1/12/04
to Luke Palmer, Internals List
On Mon, 12 Jan 2004, Luke Palmer wrote:

> > Well... A Coroutine is a pausable, resumable continuation, right?
> > Or basically a closure with a continuation inside it.
>
> Both of those sentences seem wildly redundant to me. I think we might
> be stuck on vocabulary. We're surely both understanding the same thing
> in different ways.

Yes. I was "understanding" it in the "wrong" way. :)

> A continuation is one snapshot -- it never changes, it never runs.
> To invoke the continuation is to take you back to that snapshot and
> start running from there. To invoke it a second time is exactly
> like invoking it the first time.

Thanks. I'd heard this a million times but putting it this way
made it click for me.

I've been thinking about continuations as if they were like
python functions. In python, functions are objects. You can
define them interactively at the prompt and then look inside
them and see some representation of their bytecode.

But with parrot, there's just one big long line of instructions.
A .pcc_sub isn't an object, just a little segment of the list of
instructions.

Okay... Here's a metaphor I'm working on to try and help me
understand how to picture all this. It's not finished (see
the end). Feedback appreciated:

===========


MR PARROT'S NEIGHBORHOOD

Mr Parrot lives on a very long street. Each house on the
street contains an opcode. His job is to go door to door
and follow the instructions of the little ops.

Mr Parrot carries with him as much paper as he can carry.
Each sheet has 16 boxes on it, and he has eight different
stacks of them:

int 0..15 int 16..31
num 0..15 num 16..31
str 0..15 str 16..31 # should be "string", I know
pmc 0..15 pmc 16..31

He also has about a zillion pockets on him. He can put
things in his pockets (and of course keep track of where
they are by writing it down in a pmc box). Every once
in a while, he goes through his pockets and throws out
anything he doesn't need anymore.

So starts at the first address, performs the instruction,
and then goes to whatever that opcode says. She might ask
him to write a number down in one of the boxes ("set I0, 3")
or to copy one box to another ("set I0, I1") or an object
to keep track of, or something equally simple.

Usually when he's done with the op, he just goes next door,
but sometimes the op tells him to go somewhere else, either
explicitly ("goto label") or based on the values in the
boxes ("le I0, I1, label") or the objects in his pockets
("le P0, P1, label").

Often, an op will tell him to copy the top sheet on one
(or some or all) of the stacks and put the copy on top
("push") or throw away the top sheet ("pop"). He gets
really mad if you tell him to throw away the last sheet,
or if a stack gets so big he can't carry it anymore.

Every once in a while, the op will tell Mr. Parrot to
do something like this:

- make copies of all your stacks of paper
- put the copies inside a briefcase
- write this delivery address on the briefcase
- (possibly) write a return address on the briefcase
- put the briefcase in your pocket

Is that an accurate portrayal of a continuation?

######

Now... I only described the register stacks. In docs/pmc/subs.pod
it lays out the differences between the different kinds of Subs.
It has this table:


Subtype Controlstack PadStack UserStack Warnings
------------------------------------------------------------
Sub - - - C
Closure - C - C
Continuation C C C C
Coroutine C C C C
RetContinuation X X X X

"C" ... COWed copy is in context
"X" ... is in context
"-" ... isn't.

My problem is that I don't know what a Control stack, pad stack,
user stack, and warnings are.

Here's my guess:

ControlStack {
This is another set of smaller papers. One box each.
if Mr. Parrot meets a "ret" op, he takes the
top sheet and goes to whatever address is on it.

When we call a Sub, we write the return address on
the top sheet. Same with a closure.

** I don't understand what happens here when we call
a continuation.
}

PadStack {
Hmm. Does this mean lexical pads? In which case, it's
a list of friendly names that he uses to remind him
which box or pocket a particular thing is in.
}


UserStack {
By process of elimination, this would be the eight
register stacks?
}

Warnings {
** Beats me. Is this for holding exception handlers?
}

Final questions:

What's a context?
How would I picture Eval? Does that involve building new houses?


> A coroutine is like a variable that holds continuations, and updates
> itself whenever it "yields". I guess that's the best way I can put
> it with my affliction against coming up with good similes.

Well, you just saw my attempt. I understand what a coroutine
does, but I'm still not sure how to picture it in terms of
Mr Parrot's world.

Obviously it's a briefcase of some kind. A Sub isn't a briefcase.
For a sub, he just writes a return address on the control stack
and then goes somewhere. Invoking a sub is really the same as
firing off a "push this address on the ret stack" op and then
doing a goto.

Calling a continuation is saying: "throw away all your papers,
and start over with copies of the ones in this briefcase."

The class tree in subs.pod is confusing to me:

Sub
Closure
Continuation
Coroutine
Eval
RetContinuation


For a closure, he has a briefcase but it only contains
an old copy of the pad stack. So he can open up the
briefcase and use the old pad stack to mess around
with variables that don't have names on his usual stacks
anymore. But when he meets a "ret" op, he knows to put
the old pad stack back in the briefcase and go back
tot he normal one.

That step never happens with a continuation. For a
continuation, nothing ever goes back in the briefcase,
because a continuation briefcase also contains the
control stack. So when he meets a "ret" he uses the
old copy of the control stack.

But I suppose it makes more sense if, for a closure, the
control stack stored the return address and then stored
a note that said "hey! remember to put the pad stack back
in the briefcase"...

Calling a coroutine though is different. Each time you call
one, Mr Parrot SWAPS what's in his hands for what's in the
briefcase. At least, I think that's what swap_context() does.
I'm not sure I understand why he does that. :)


> But it's easy to implement a loop using a single continuation. Like
> this:
>
>
> newsub $P0, .Continuation, again
> again:
> # ... loop body
> invoke $P0


Sure. So the stacks are always the same every time
Mr Parrot reaches "again:", but the objects in his
pockets might have changed. He's probably gone on
plenty of wonderful adventures since the last time
he was there, and had a real effect on the
neighborhood, but he doesn't remember any of it. :)


Whew... I didn't mean to write so much... But it seems
like this metaphor might make a good user friendly
intro to parrot internals... (Assuming I got it right)

Leopold Toetsch

unread,
Jan 13, 2004, 4:01:32 AM1/13/04
to Michal Wallace, perl6-i...@perl.org
Michal Wallace <mic...@sabren.com> wrote:
> A .pcc_sub isn't an object, just a little segment of the list of
> instructions.

A pcc_sub *is* an object:

find_global P0, "_the_sub"
invokecc
print "back\n"
end
.pcc_sub _the_sub:
print "in sub\n"
invoke P1

You can store it away, pass it around and so on.

> My problem is that I don't know what a Control stack, pad stack,
> user stack, and warnings are.

> Here's my guess:

> ControlStack {
> This is another set of smaller papers. One box each.
> if Mr. Parrot meets a "ret" op, he takes the
> top sheet and goes to whatever address is on it.

Yes, its used for C-like function calls, where the return address is on
the control stack. But more importantly: the control stack has exception
handlers on it. If you install an exception handler, its pushed onto the
control stack. If an exception is thrown, the handler is popped off that
stack and control transfers to the handler subroutine.

> When we call a Sub, we write the return address on
> the top sheet. Same with a closure.

No. Subs and Closures are invoked, no control stack is involved

> ** I don't understand what happens here when we call
> a continuation.

Same here.

> PadStack {
> Hmm. Does this mean lexical pads?

Yep. C< { my $i; } > would create/push a new lexical pad with that
variable name inside.

> UserStack {
> By process of elimination, this would be the eight
> register stacks?

No. Its an intermediate store to save registers. Its used:
a) for C-style function calls
b) to get at return results, if the caller did save all 32 registers:

pushp # save P0..P31 to register frame
invoke # call a sub - result in P5
save P5 # save P5 onto user stack
popp # restore P0-P31 from register frames
restore P5 # pop off result from user stack

> Warnings {
> ** Beats me. Is this for holding exception handlers?

This are the warning flags. When you call a sub and that turns off
warnings, the warning flags are restored to the original state, when the
sub returns.

> Final questions:

> What's a context?

The context holds pointers to all these stacks and structures. The
semantics of the different Sub types define, how to deal with items in
the context. E.g. a Closure has the callers pad stack in its context, so
that a Closure can access lexicals of the caller.

> How would I picture Eval? Does that involve building new houses?

A new street with new houses.

> For a sub, he just writes a return address on the control stack

No, not for Parrot Calling Conventions. A Sub is an object.

Again: We have 2 calling conventions:
1) C-style
2) PCC

Only 1) is using return addresses pushed onto the Control Stack.

> The class tree in subs.pod is confusing to me:

> Sub
> Closure
> Continuation
> Coroutine
> Eval
> RetContinuation

These are all for 2) - no pushed return address is involved.

> Michal J Wallace

leo

Tim Bunce

unread,
Jan 13, 2004, 10:56:27 AM1/13/04
to Leopold Toetsch, Michal Wallace, perl6-i...@perl.org
On Tue, Jan 13, 2004 at 10:01:32AM +0100, Leopold Toetsch wrote:
> Michal Wallace <mic...@sabren.com> wrote:
>
> > Here's my guess:
>
> [lots of good stuff from leo]

Is there a "Parrot Architecture Overview" document that summarises
this kind of high-level view with links to the deeper docs?

If not it would be great to have.

Tim.

Melvin Smith

unread,
Jan 13, 2004, 1:46:32 PM1/13/04
to Michal Wallace, Luke Palmer, Internals List
At 11:18 PM 1/12/2004 -0500, Michal Wallace wrote:
>On Mon, 12 Jan 2004, Luke Palmer wrote:
> > A continuation is one snapshot -- it never changes, it never runs.
> > To invoke the continuation is to take you back to that snapshot and
> > start running from there. To invoke it a second time is exactly
> > like invoking it the first time.
>
>Thanks. I'd heard this a million times but putting it this way
>made it click for me.

One important addition:

While continuations are snapshots of execution context (execution path and
variables), they are not snapshots of values.

References to globals or lexicals will be restored as the snapshot, but
their values can change.

-Melvin


Dan Sugalski

unread,
Jan 15, 2004, 11:01:08 AM1/15/04
to Melvin Smith, Michal Wallace, Luke Palmer, Internals List

As will references to strings and PMCs that are on the stacks but not
in globals or lexicals.

Unfortunately ints and floats on the stacks *are* snapshots, which is
somewhat problematic in some cases.

Dan Sugalski

unread,
Jan 15, 2004, 11:02:38 AM1/15/04
to Tim Bunce, Leopold Toetsch, Michal Wallace, perl6-i...@perl.org

I'll see if I can dig up some text to put in. I've written the doc a
dozen times or more so far, but it's all been in presentations and
articles. (It's going to be a documentation week, I can tell)

I'll assume everyone (including CVS) can handle PNG images, since I
think I may need some diagrams.

0 new messages