Optimizations for Objects

1 view
Skip to first unread message

Dan Sugalski

unread,
Mar 17, 2004, 11:53:16 AM3/17/04
to perl6-i...@perl.org
Okay, as I see it there are two big things that we can do to speed
objects up. (Well, besides speeding up the creation of continuation
PMCs, which I am, at the moment, sorely tempted to put in a special
pool for fast allocation) They are:

1) A method cache. Which we need anyway, so this isn't any surprise

2) Pre-figuring the delegated vtable functions.

#1 is a pretty straightforward thing, I'll detail my scheme in a bit.

#2 is where I think we can get some wins, though without a
notification system it's a bit dodgy. (A fixable one, though)

What I'm considering for a vtable method-specific cache is pretty
straightforward. When we build a class we allocate a new vtable for
it, though the vtable's essentially just a clone of the delegate
vtable. Make a call and we do a method lookup and then call it.

That's all fine and good, and the generic method cache will help
here. However... we can do better. What I'm thinking of is caching
the actual found method PMC pointer in the class somewhere (hanging
off the vtable or in the class' attributes or something) such that we
don't actually have to *do* any method lookups. With the method PMC
directly cached, we just call the darned thing and are done with it.
No lookups at all, something definitely faster than actually looking
anything up.

At the moment I'm considering two storage schemes for the PMC
pointers (one hanging off the vtable itself, another in the class
attributes) but I'm open to suggestions here.
--
Dan

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

Zellyn Hunter

unread,
Mar 17, 2004, 12:49:49 PM3/17/04
to perl6-i...@perl.org
Might be worth looking at Smalltalk papers too - they've been doing objects
forever. If I remember correctly, some smalltalks have an interesting form
of caching: they call the last thing the call resolved to, and redispatch as
necessary. So rather than looking things up before every call, you make the
same call as last time, and the called routine does:

a) are we supposed to be here? (presumed to be cheaper)
b) if not, redispatch and re-cache (presumed to be more expensive)
c) main method body

I'm not sure if that's apropos, but I thought it was quite clever when I first
read about it. Searching the web for [smalltalk cache] pulls up some
interesting info and discussions.

Zellyn

Leopold Toetsch

unread,
Mar 17, 2004, 12:46:50 PM3/17/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> Okay, as I see it there are two big things that we can do to speed
> objects up. (Well, besides speeding up the creation of continuation
> PMCs, which I am, at the moment, sorely tempted to put in a special
> pool for fast allocation)

I though about that already. Returncontinuations created via the *cc
opcode variants are created in the opcode and used exactly once just for
returning from the sub. So I'd do for these a per-interpreter
freelist, where they get put back after invokeing the return
contination.

> 1) A method cache. Which we need anyway, so this isn't any surprise

> 2) Pre-figuring the delegated vtable functions.

> At the moment I'm considering two storage schemes for the PMC


> pointers (one hanging off the vtable itself, another in the class
> attributes) but I'm open to suggestions here.

Or: after the 1st delegate lookup create a JITed stub that is in
pseudo-code:

enter
call saveregs
S0 = "meth"
P2 = obj
P5 = value # arguments
call runops
call restoreregs
# handle return val
leave
ret

This function's address replaces the vtable slot of the old one and is
now called directly as the delegate. When the register assignments are
done interpreter-relative, this stub should be reusable by different
threads too.

> --
> Dan

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

leo

Dan Sugalski

unread,
Mar 17, 2004, 1:01:08 PM3/17/04
to l...@toetsch.at, perl6-i...@perl.org
At 6:46 PM +0100 3/17/04, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
>> Okay, as I see it there are two big things that we can do to speed
>> objects up. (Well, besides speeding up the creation of continuation
>> PMCs, which I am, at the moment, sorely tempted to put in a special
>> pool for fast allocation)
>
>I though about that already. Returncontinuations created via the *cc
>opcode variants are created in the opcode and used exactly once just for
>returning from the sub. So I'd do for these a per-interpreter
>freelist, where they get put back after invokeing the return
>contination.

Unless something inside the call's taken a continuation, in which
case they're still valid and may be reused. Can't do that,
unfortunately. :(

I was thinking of a special PMC arena for continuations that already
had the full data chunk tacked on the end of the struct and the
various PMC pointers-to-data filled in.

> > 1) A method cache. Which we need anyway, so this isn't any surprise
>
>> 2) Pre-figuring the delegated vtable functions.
>
>> At the moment I'm considering two storage schemes for the PMC
>> pointers (one hanging off the vtable itself, another in the class
>> attributes) but I'm open to suggestions here.
>
>Or: after the 1st delegate lookup create a JITed stub

Which is swell, except for that pesky can't-guarantee-a-JIT thing... :)

Sterling Hughes

unread,
Mar 17, 2004, 12:06:35 PM3/17/04
to Dan Sugalski, perl6-i...@perl.org
>
> That's all fine and good, and the generic method cache will help here.
> However... we can do better. What I'm thinking of is caching the
> actual found method PMC pointer in the class somewhere (hanging off
> the vtable or in the class' attributes or something) such that we
> don't actually have to *do* any method lookups. With the method PMC
> directly cached, we just call the darned thing and are done with it.
> No lookups at all, something definitely faster than actually looking
> anything up.
>

How do you handle the threaded case with two private objects and
runtime method overloading?

-Sterling

Leopold Toetsch

unread,
Mar 17, 2004, 4:11:45 PM3/17/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> At 6:46 PM +0100 3/17/04, Leopold Toetsch wrote:
>>
>>I though about that already. Returncontinuations created via the *cc
>>opcode variants are created in the opcode and used exactly once just for
>>returning from the sub. So I'd do for these a per-interpreter
>>freelist, where they get put back after invokeing the return
>>contination.

> Unless something inside the call's taken a continuation, in which
> case they're still valid and may be reused. Can't do that,
> unfortunately. :(

Could you please provide a code snippet that shows this reusing.

Thanks,
leo

Larry Wall

unread,
Mar 17, 2004, 5:38:40 PM3/17/04
to perl6-i...@perl.org
On Wed, Mar 17, 2004 at 12:06:35PM -0500, Sterling Hughes wrote:
: >
: >That's all fine and good, and the generic method cache will help here.

I suspect Dan is primarily talking about public, single dispatch in
a (more-or-less) static, global class hierarchy. Private dispatch
shouldn't be trying to use the public dispatcher in any case, in
my opinion, and Perl 6 will enforce that by making you call private
methods differently from public methods, to keep private things in a
completely separate namespace. (Whether Parrot will have to confuse
the private and public dispatchers to support other languages is
another matter, of course... But we'd prefer not to violate Liskov
substitutability just because you add a private method.)

Larry

Mitchell N Charity

unread,
Mar 17, 2004, 6:32:54 PM3/17/04
to perl6-i...@perl.org
It's always nice to have numbers when planning optimizations.

So I started fiddling with oofib.imc.

It seemed like we were spending a lot of time copying strings.
So I defined the method name strings once, in main,
$S3 = "fibB"
and replaced calls like
self.fibB(n2)
with
self.$S3(n2)
Optimized and unoptimized reported run times went down 10%.
That's 1/5 of the way to perl! :)

I would like to see at least two other tests:

(1) doing fetch_method in main, and using the fetched methods,
rather than repeatedly looking them up.

(2) creating an explicit return continuation in fib, and using
it for both recursive calls, cutting continuation creation
in half.

The first will illustrate the maximum savings we can expect here
from a perfect, costless, method lookup cache.

The second will illustrate how much time is being spent in return
continuation pmc creation and associated garbage collection.

What else might be interesting?


I began work on (1), but got bogged down.
Perhaps a better imc writer than I could knock it off?


I just don't have that warm fuzzy feeling that we know where our time
is going yet.

Mitchell

Mitchell N Charity

unread,
Mar 18, 2004, 4:10:59 PM3/18/04
to perl6-i...@perl.org
It seemed nontrivial to reduce the number return continuation pmc's
used in oofib.imc. So I instead added an _extra_, unused one, to the
two already used in each fib method.

Parrot ran 30% slower. (Optimized, unoptimized, and jit)

Which suggests return continuation pmc driven memory management costs
(gc and allocation) are currently a major, perhaps even dominant,
factor in method invocation speed.

Mitchell

Dan Sugalski

unread,
Mar 18, 2004, 4:04:50 PM3/18/04
to mcha...@vendian.org, perl6-i...@perl.org

Yow. Okay, thanks. That means it's time to dive into the think tank
and see what we can do about that.

Leopold Toetsch

unread,
Mar 18, 2004, 4:38:50 PM3/18/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> At 4:10 PM -0500 3/18/04, Mitchell N Charity wrote:
>>It seemed nontrivial to reduce the number return continuation pmc's
>>used in oofib.imc. So I instead added an _extra_, unused one, to the
>>two already used in each fib method.
>>
>>Parrot ran 30% slower. (Optimized, unoptimized, and jit)
>>
>>Which suggests return continuation pmc driven memory management costs
>>(gc and allocation) are currently a major, perhaps even dominant,
>>factor in method invocation speed.

> Yow. Okay, thanks. That means it's time to dive into the think tank
> and see what we can do about that.

Which brings up again my warnocked question: How can return
continuations get reused? Please provide some PASM code that enables my
brain to follow your argument that we cant't simply cache them.

leo

Mitchell N Charity

unread,
Mar 18, 2004, 5:32:30 PM3/18/04
to perl6-i...@perl.org
>Which suggests return continuation pmc driven memory management costs
>(gc and allocation) are currently a major, perhaps even dominant,
>factor in method invocation speed.

Yow. Okay, thanks. That means it's time to dive into the think tank
and see what we can do about that.

Nothing like finally thinking of caveats _after_ hitting send.

oofib as a program is generating atypically(?) little garbage.
So much of the garbage is continuation pmcs, which thus determine the
frequency of costly gc sweeps. In a dirtier, more typical environment,
where perhaps other factors are determining the frequency of gc sweeps,
the gc cost would look more like the pmc's _incremental_ cost of
collection. Maybe. Which would be less "yow". How much less isn't
clear. Though given that allocating these pmc's seems to be itself say
1/3 of method call cost without considering gc, they would retain at
least that level of yow.

Mitchell
(btw, regards ICU progress... awesome!!:)

Dan Sugalski

unread,
Mar 18, 2004, 5:31:44 PM3/18/04
to l...@toetsch.at, perl6-i...@perl.org
At 10:38 PM +0100 3/18/04, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
>> At 4:10 PM -0500 3/18/04, Mitchell N Charity wrote:
>>>It seemed nontrivial to reduce the number return continuation pmc's
>>>used in oofib.imc. So I instead added an _extra_, unused one, to the
>>>two already used in each fib method.
>>>
>>>Parrot ran 30% slower. (Optimized, unoptimized, and jit)
>>>
>>>Which suggests return continuation pmc driven memory management costs
>>>(gc and allocation) are currently a major, perhaps even dominant,
>>>factor in method invocation speed.
>
>> Yow. Okay, thanks. That means it's time to dive into the think tank
>> and see what we can do about that.
>
>Which brings up again my warnocked question: How can return
>continuations get reused?

Works like this. (No pasm, but it should be obvious)

sub a:
build return continuation X
call sub b
do processing
return

sub b:
do some processing
take continuation Y
store Y in global variable Z
exit

main:
call sub a
grab continuation Y from variable Z
invoke continuation Y

If a continuation's taken from within a sub somewhere, return
continuations may (probably will) be used multiple times, once for
the original return then once for each time the continuation is
invoked.

Jens Rieks

unread,
Mar 18, 2004, 5:48:52 PM3/18/04
to l...@toetsch.at, perl6-i...@perl.org
Hi,

See attachment.

> leo
jens

Jens Rieks

unread,
Mar 18, 2004, 5:52:50 PM3/18/04
to perl6-i...@perl.org
oops, I renamed the wrong file...
This is the correct example.

jens

reuse.pasm

Mitchell N Charity

unread,
Mar 18, 2004, 6:42:07 PM3/18/04
to perl6-i...@perl.org
Which brings up again my warnocked question: How can return
continuations get reused? Please provide some PASM code that enables my
brain to follow your argument that we cant't simply cache them.

Well, I can't do PASM code, but let me give it try. ;)

Single vs multiple use. It should be possible to give the same
continuation to multiple people, and have them variously invoke it,
perhaps repeatedly, whenever someone wants to. Though all those
invocations would come to the same "place", so if you wished to
distinguish just who was invoking you, you would have to cooperatively
arrange for that yourself (or use something like caller()).

"Reuse" implies something stronger. That the continuation becomes
somehow invalid, and thus its dead husk can be used to host a new
continuation.

As continuations can be stashed anyplace, and invoked at any later
time, the only way to know folks are done with it is wait until it
gets garbage collected. So one might say create a special memory
pool, used just for continuations, which might perhaps allow for easier
construction.

Forcing a continuation to become invalid, to say throw an exception if
it is later invoked, would seem to require something like creating a
derivative "revocable continuation", and uid in normal continuations.
So one gives people the revocable continuation, and if/when it's
underlying continuation is "reused", it's uid is changed, which the
derivative checks when deciding whether to invoke it, or to die.

Some memory systems allow one to forcibly declare an object dead, and
subsequent use triggers an exception. But you don't get to reuse the
object. Unless there is an extra level of indirection between object
ids and their memory, which we don't have.

It's not clear to me what "return" continuations are intended to be.
Up-calls? This would not avoid the "can it be reused now?" question,
as one might stash one's return continuation in say a timer, to be
invoked again on every third tuesday.

One might try to contractually enforce a "one use only" rule, so if
the continuation is ever invoked, you're promised it won't be used
again. But that would have to be binding on the entire call tree
beneath you. And on anyone who might reflectively snoop on the call
tree. :) Otherwise anyone could stash _their_ continuation, and by
later reinvoking it, reinvoke yours. Though you might generate
"firewall" one-use code objects to insulate yourself, but... blech.
However, language compilers are of course free to use their own
calling conventions when dealing only with themselves, where they can
make any kind of strange guarantee they wish. They just wouldnt be
able to call out of these specialized zones, without significant
border guarding.

So I don't immediately see how a continuation can be "reused" in a
now-it-will-do-something-different sense.

Then again, there _is_ this "return continuation" thing in the code.
I just cant quite figure out what it is... ;)

Mitchell

Leopold Toetsch

unread,
Mar 19, 2004, 2:57:28 AM3/19/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> At 10:38 PM +0100 3/18/04, Leopold Toetsch wrote:
>>
>>Which brings up again my warnocked question: How can return
>>continuations get reused?

> Works like this. (No pasm, but it should be obvious)

Ok. First (and that applies to Jens example too), I'd like to outline
continuation vs return continuation and its usage:

1) First there was only a Continuation PMC. Performance with CPS sucked.
So I did invent a RetContinuation PMC Performance sucked less. The
difference between these two is: the former has COW copied stacks inside
its context, the latter has only pointers of the stacks in its context.

2) A return continuation is automatically created by

invokecc
callmethodcc

It's totally hidden when using PIR function or method call syntax

_func(a, b)
obj."meth"(args)

These internally create above opcodes and create a new return
continuation on each sub or method invocation

3) Returning from the sub or method in PIR syntax again totally hides
the return continuation

.pcc_begin_return
.return result
.pcc_end_return
.end

or just

.sub _foo
.end # automatic return sequence inserted.

4) From PIR level there is no official way to even reference this return
continuation - its invisible.

5) *But*

> If a continuation's taken from within a sub somewhere, return
> continuations may (probably will) be used multiple times, once for
> the original return then once for each time the continuation is
> invoked.

6) Yes, that's true. So the questios is: Can we invent some HLL PIR
syntax that clearly indicates: this subroutine will return multiple
times through the same return continuation. We have already a similar
construct for Coroutines:

.pcc_begin_yield
.result # optional
.pcc_end_yield

This is invokeing the coroutine and returns to the caller.

What's the usage of Continuations from HLLs point of view? Can we get
some hints, what is intended?

I'd like to have, if possible a clear indication: that's a plain
function or method call and this is not. I think the possible speedup is
worth the effort.

leo

Piers Cawley

unread,
Mar 19, 2004, 6:21:43 AM3/19/04
to l...@toetsch.at, Dan Sugalski, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:

I think that requires solving the halting problem.

Brent 'Dax' Royal-Gordon

unread,
Mar 19, 2004, 7:25:14 AM3/19/04
to Piers Cawley, l...@toetsch.at, Dan Sugalski, perl6-i...@perl.org
I may have a possible solution. Disclaimer: I do not really understand
continuations, so I may be completely wrong.

This idea involves two assumptions:

1. Most Parrot code will not use continuations except for returning.
(There will be a significant efficiency loss otherwise.)

2. The most expensive part of constructing a continuation is COWing
the stack, etc.--simply constructing the data structure is cheap.

3. A return continuation may be safely reused if:
a. It has not been stored externally.
b. None of the return continuations for subroutines it has called
(recursively speaking) have been stored externally.
c. No other continuations have been constructed.

Here's how it works:

A ReturnContinuation is a lightweight version of a normal Continuation;
it contains the information needed to create a Continuation, but is not
really a continuation itself. Once allocated, a ReturnContinuation is
never[1] truly deallocated; if it dies, it's put on a free list, and
will be reused if it's needed.

Before a ReturnContinuation may be stored externally (and thus have the
possibility of being invoked later), it has to be transformed into a
normal Continuation. This will probably require compilers (or IMCC) to
insert an extra instruction, but I don't think that'd be too difficult.
(A naive way to do it would be to simply emit a second/different
instruction whenever P1 is retrieved. It might be possible to make IMCC
do this, or even to write this into the 'set' op.)

If a program either creates a normal Continuation or transforms a
ReturnContinuation into a normal one, Parrot will automatically turn all
currently-live ReturnContinuations into normal Continuations. (How is
an unknown, admittedly--perhaps we'll keep a list of currently-live
ReturnContinuations, too.) This means that your return continuation may
in fact be a real Continuation instead of a ReturnContinuation.

If a ReturnContinuation is invoked without being stored externally (and
thus transformed into a real Continuation), it is immediately considered
dead, and returns to the free list.

The effect is that the heavy work of constructing real Continuations is
deferred until we have a good reason to believe they'll be needed. For
programs that never use continuations except for old-fashioned
returning, a lot of work is avoided, because ReturnContinuations are
faster to construct; for programs that do use continuations, a little
extra work is done, because it would have been faster to construct real
Continuations in the first place. I suspect this would usually be a
win, although it might be wise to give the language compiler a way to
say "I know this program will use continuations, so just construct them
that way in the first place."


Example:

A calls B, creates ReturnContinuation rA1.
B calls C, creates ReturnContinuation rB1.
C invokes ReturnContinuation rB1 to return to B.
ReturnContinuation rB1 returns to the free list.
B calls D, creates ReturnContinuation rB2 (ex-rB1?).
D stores rB2 into Z:
rB2 becomes a real Continuation.
rA1 becomes a real Continuation.
D invokes Continuation rB2 to return.
Continuation rB2 does *not* return to the free list.
B calls E, creates ReturnContinuation rB3.
E invokes ReturnContinuation rB3 to return.
ReturnContinuation rB3 returns to the free list.
B invokes Continuation rA1 to return.
Continuation rA1 does *not* return to the free list.
A calls F, creates ReturnContinuation rA2 (ex-rB3?).
F creates and stores a new Continuation into Y:
rA2 becomes a real Continuation.
F invokes rA2 to return.
Continuation rA1 does *not* return to the free list.
A invokes Z--control jumps to the next statement in B after the call to D.


[1] Conceptually, that is. Realistically, it might make sense to do so
if you have a few thousand spare return continuations floating around.

--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker

Oceania has always been at war with Eastasia.

Ibotty

unread,
Mar 19, 2004, 9:39:32 AM3/19/04
to perl6-i...@perl.org
> This idea involves two assumptions:

there are three kinds of people.
those that can count and the others ;)

~ibotty

Larry Wall

unread,
Mar 19, 2004, 3:44:42 PM3/19/04
to perl6-i...@perl.org
On Fri, Mar 19, 2004 at 08:57:28AM +0100, Leopold Toetsch wrote:
: What's the usage of Continuations from HLLs point of view? Can we get

: some hints, what is intended?

From the standpoint of Perl 6, I hope to hide continuations far, far
away in a galaxy long ago. No wait, wrong movie...

We can certainly make it the default that a routine is not going to
do anything fancy with continuations unless it is explicitly declared
to allow it. As to what that declaration should be, I have no idea.
Probably just a trait that says, "is continuationalizableish" or
some such.

: I'd like to have, if possible a clear indication: that's a plain


: function or method call and this is not. I think the possible speedup is
: worth the effort.

I have no problem with "plain" being the default. I suppose you could
declare it explicitly if you like:

sub foo () is plain {...}

Then obviously the other kind would be:

sub bar () is peanut {...}

Hmm, actually, "smooth" and "nutty" might be more accurate.

Larry

James Mastros

unread,
Mar 19, 2004, 4:32:21 PM3/19/04
to perl6-i...@perl.org, Larry Wall
Larry Wall wrote:
> We can certainly make it the default that a routine is not going to
> do anything fancy with continuations unless it is explicitly declared
> to allow it. As to what that declaration should be, I have no idea.
> Probably just a trait that says, "is continuationalizableish" or
> some such.
"is mindwarping"? "does the_time_warp_again"?

The problem, in any case, is similar to "throws" in Java: if any of your
children are marked, so shall you be, unto the Nth generation. (Or, at
least, this is how I understand it.)

-=- James Mastros

Leopold Toetsch

unread,
Mar 19, 2004, 5:06:06 PM3/19/04
to Larry Wall, perl6-i...@perl.org

There is of course no need to declare the default, which will be very
likely beyond 99%. I won't discuss P6 syntax here, which could lead to

sub bar() will reuse_P1 { ... }

Piers' statement was related to solving the halting problem, which isn't
really positive. I don't throw or catch pies, but CPS returns are
currently the major performance loss Parrto has.

> Larry

leo

Piers Cawley

unread,
Mar 20, 2004, 4:22:04 AM3/20/04
to l...@toetsch.at, Larry Wall, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:

I argue that we have the problems we do (incorrect behaviour of
continuations, horrible allocation performance) because we chose the
wrong optimization in the first place. The stack optimizations that are
in place make sense when you don't have continuations, but once you do,
the cost of allocating a continuation and maintaining all that COW
complexity becomes prohibitive. I strongly advocate rejigging the
stacks so that one stack frame = 1 stacked thing + 1 link to the next
thing in the chain. No need for COW, no need for memcpy when allocating
continuations, no worrying complexity to deal with while you're trying
to get the behaviour right. Oh, an no need for RetContinuations either.

Leopold Toetsch

unread,
Mar 20, 2004, 7:10:58 AM3/20/04
to Piers Cawley, perl6-i...@perl.org
Piers Cawley <pdca...@bofh.org.uk> wrote:

> I argue that we have the problems we do (incorrect behaviour of
> continuations, horrible allocation performance) because we chose the
> wrong optimization in the first place. The stack optimizations that are
> in place make sense when you don't have continuations, but once you do,
> the cost of allocating a continuation and maintaining all that COW
> complexity becomes prohibitive. I strongly advocate rejigging the
> stacks so that one stack frame = 1 stacked thing + 1 link to the next
> thing in the chain. No need for COW, no need for memcpy when allocating
> continuations, no worrying complexity to deal with while you're trying
> to get the behaviour right. Oh, an no need for RetContinuations either.

The current problem of e.g. the oofib benchmark isn't related to that.
Actually it doesn't COW copy stacks. A RetContinuation just does a
memcpy of the context structure, that's it.

Creating RetContinuations is only one factor, the major is the missing
method cache. C<callmethodcc> takes almost 3 times the time of creating a
RetContinuation.

leo

Dan Sugalski

unread,
Mar 20, 2004, 11:18:08 AM3/20/04
to perl6-i...@perl.org
At 12:44 PM -0800 3/19/04, Larry Wall wrote:
>On Fri, Mar 19, 2004 at 08:57:28AM +0100, Leopold Toetsch wrote:
>: What's the usage of Continuations from HLLs point of view? Can we get
>: some hints, what is intended?
>
>From the standpoint of Perl 6, I hope to hide continuations far, far
>away in a galaxy long ago. No wait, wrong movie...

Which is swell, but Perl 6 is only one of the languages we care
about. Ruby does, and while it's not exactly one of the primary
targets, scheme and lisp are heavily laced with them.

>We can certainly make it the default that a routine is not going to
>do anything fancy with continuations unless it is explicitly declared
>to allow it.

Can't do that. There's no way you can ever really know that, since
any function or method you call might take one. Forbidding it is
going to be problematic as well, since then we hit performance issues
in guaranteeing that.

Larry Wall

unread,
Mar 20, 2004, 11:31:40 AM3/20/04
to perl6-i...@perl.org
On Sat, Mar 20, 2004 at 11:18:08AM -0500, Dan Sugalski wrote:
: At 12:44 PM -0800 3/19/04, Larry Wall wrote:
: >On Fri, Mar 19, 2004 at 08:57:28AM +0100, Leopold Toetsch wrote:
: >: What's the usage of Continuations from HLLs point of view? Can we get
: >: some hints, what is intended?
: >
: >From the standpoint of Perl 6, I hope to hide continuations far, far
: >away in a galaxy long ago. No wait, wrong movie...
:
: Which is swell, but Perl 6 is only one of the languages we care
: about. Ruby does, and while it's not exactly one of the primary
: targets, scheme and lisp are heavily laced with them.

I understand that, which is why I said "From the standpoint of Perl 6".

: >We can certainly make it the default that a routine is not going to


: >do anything fancy with continuations unless it is explicitly declared
: >to allow it.
:
: Can't do that. There's no way you can ever really know that, since
: any function or method you call might take one. Forbidding it is
: going to be problematic as well, since then we hit performance issues
: in guaranteeing that.

Well, Leo asked for hints, and I basically said Perl has no problem
sending them. If Parrot has a problem receiving them, that's another
matter. :-)

Larry

Melvin Smith

unread,
Mar 20, 2004, 11:53:06 AM3/20/04
to l...@toetsch.at, Dan Sugalski, perl6-i...@perl.org
At 08:57 AM 3/19/2004 +0100, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
> > At 10:38 PM +0100 3/18/04, Leopold Toetsch wrote:
> >>
> >>Which brings up again my warnocked question: How can return
> >>continuations get reused?
>
> > Works like this. (No pasm, but it should be obvious)

I was aware of Leo's RetContinuation because our initial
implementation using a full Continuation was deemed a little
heavy.

As long as the RetContinuation honors Copy On Write, there
should be no problem unless the RetContinuation is stored
and referenced "outside" the original scope (or escapes the
closure of the sub call or full continuation).

The problem could be that some code is not honoring COW
and it is not copying things before using.

-Melvin


Leopold Toetsch

unread,
Mar 20, 2004, 12:32:11 PM3/20/04
to perl6-i...@perl.org
Larry Wall wrote:

> Well, Leo asked for hints, and I basically said Perl has no problem
> sending them. If Parrot has a problem receiving them, that's another
> matter. :-)

When there are now hits from languages like Ruby or Smalltalk, then one
single flag will do it: If ever a real Continuation is created, this
optimization will be stopped. That's hint enough.
If this flag isn't set, RetContinuations will be recycled immediately on
an extra free list (and allocated from that).

I've running here a method cache now (passes already all but 1 test).
Speedup (unoptimized build) is aroud one third.


> Larry

leo


Gerald E Butler

unread,
Mar 20, 2004, 11:33:10 AM3/20/04
to perl6-i...@perl.org
Hello all,

I've been investigating the possibility of creating a MACHINE
DESCRIPTION (aka BACK-END) for GCC to target PARROT. My thinking is
this: If a satisfactory GCC back-end targeting PARROT is created -and-
PARROT is efficient enough (which from reading the documentation thus
far produced seems like it is an inevitable conclusion) then GCC could
compile itself to PARROT byte-code giving PARROT (and the whole open
source community) a PARROT self-host compiler which compiles multiple
languages (C#, C++, C, Pascal, Objective-C, Java, etc, etc, etc) to the
PARROT runtime.

Is a complete non-starter, or is this something which has
possibilities? Please give your expert opinions.

James Mastros

unread,
Mar 21, 2004, 4:49:30 AM3/21/04
to Gerald E Butler, perl6-i...@perl.org
Gerald E Butler wrote:
> I've been investigating the possibility of creating a MACHINE
> DESCRIPTION (aka BACK-END) for GCC to target PARROT. My thinking is
> this: If a satisfactory GCC back-end targeting PARROT is created -and-
> PARROT is efficient enough (which from reading the documentation thus
> far produced seems like it is an inevitable conclusion) then GCC could
> compile itself to PARROT byte-code giving PARROT (and the whole open
> source community) a PARROT self-host compiler which compiles multiple
> languages (C#, C++, C, Pascal, Objective-C, Java, etc, etc, etc) to the
> PARROT runtime.

At first glance, this looks like a good thing to do. After all, Parrot
was made a register machine, instead of a stack machine, to be able to
leverage the existing art with reference to real machines, which are
register machines, not stack machines.

So what's the problem?

In a word: Memory. GCC expects the machine to be more or less like a
real machine. This means, in no small part, that it has a large amount
of memory, accessible by getting a pointer to it, which is an integer.
Now, it would be possible to emulate that with an appropriately-crafted
PMC.

So is it possible, after you write that PMC?

Well... in theory, if you do this, you can write a gcc backend targeting
parrot. It shouldn't even be /that/ difficult. (More difficult then
porting gcc to a more traditional arch, less difficult then writing your
own C, etc, compiler.)

Unfortunately, since you've created that "memory" PMC, and stuffed much
of your data in it, you no longer have assembler that resembles, even
vaguely, that of the rest of the parrot world. Heck, most languages
will end up putting most user-visible things in PMC registers, and
you'll only ever use one. You'll never use string registers. You've
got an implicit PMC argument to every function, and one that probably
wants highlander (singleton) semantics as well.

You can write C, C#, C++, Pascal, Objective-C, Java, etc, but it won't
interoperlate with other Parrot code well (without stubs), if at all
(the stubs may be quite difficult).

Is it worthwhile anyway?

Quite possibly.

Is it easy?

No.

Will it do everything you want it to do?

No.

-=- James Mastros

Gerald E Butler

unread,
Mar 21, 2004, 10:32:04 AM3/21/04
to James Mastros, perl6-i...@perl.org