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

indexing registers or something

9 views
Skip to first unread message

K Stol

unread,
May 13, 2003, 11:14:41 AM5/13/03
to perl6-i...@perl.org
hello,

I've got a very strange idea, and probably it doesn't make sense for other people, but maybe someone sees something in it.

The idea is the following. Assume there are some values on the runtime stack, let's say "1", "2", "3".
Now, if they should be restored in a series of registers, say registers P5 to P7, it would be nice to do that in a loop,
so that "1" will be put in P5, "2" in P6, etc.

here's what I'd like: (I3 has number of values)

set x, 5 -- can not be done, pseudo code
L1:
eq I3, 0, L2
restore Px -- first time restore in P5
inc x -- next time, restore in P6, then P7, etc.
dec I3
branch L1
L2:

What you would need is a variable keeping the name of a register, or its number, and a way to set it to some value.
(the alternative to this is flattening the loop , which would be a *lot* of code.)

Or is this utterly impossible/not desirable?
Klaas-Jan.

Benjamin Goldberg

unread,
May 13, 2003, 4:43:36 PM5/13/03
to perl6-i...@perl.org

It would be impossible, or nearly impossible, to generate jit code for
such ops.

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Steve Fink

unread,
May 14, 2003, 1:08:56 PM5/14/03
to Benjamin Goldberg, perl6-i...@perl.org
On May-13, Benjamin Goldberg wrote:
>
>
> K Stol wrote:
> >
> > hello,
> >
> > I've got a very strange idea, and probably it doesn't make sense for other people, but maybe
> > someone sees something in it.
> >
> > The idea is the following. Assume there are some values on the runtime stack, let's say "1",
> > "2", "3". Now, if they should be restored in a series of registers, say registers P5 to P7,
> > it would be nice to do that in a loop, so that "1" will be put in P5, "2" in P6, etc.
> >
> > here's what I'd like: (I3 has number of values)
> >
> > set x, 5 -- can not be done, pseudo code
> > L1:
> > eq I3, 0, L2
> > restore Px -- first time restore in P5
> > inc x -- next time, restore in P6, then P7, etc.
> > dec I3
> > branch L1
> > L2:
> >
> > What you would need is a variable keeping the name of a register, or its number, and a way
> > to set it to some value.
> > (the alternative to this is flattening the loop , which would be a *lot* of code.)
> >
> > Or is this utterly impossible/not desirable?
>
> It would be impossible, or nearly impossible, to generate jit code for
> such ops.

The JIT could generate a jump table for the various operations:

set_P0: set P0, r0
ret
set_P1: set P1, r0
ret
.
.
.
get_P0: set r0, P0
ret
get_P1: set r0, P1
ret
.
.
.

where r0 is a processor register, not a Parrot register.
Unfortunately, the 'bsr get_Px_table[x]' instruction would invalidate
all JIT register mappings.

Alternatively, we could treat the register sets as "memory-mapped
registers", so that writes to particular regions are equivalent to
writes to the appropriate register or registers. Except that in
Parrot, we don't currently have a notion of "memory", so it would be
done through a magic PMC or perhaps we'd just invent syntax for it.
This would still force the JIT to invalidate its register mappings.

Not that I'm arguing for implementing such a thing, but the word
"impossible" is such irresistible bait... :-)

Dan Sugalski

unread,
May 15, 2003, 7:41:33 AM5/15/03
to perl6-i...@perl.org

Nah, not really. They'd just need to do the same sort of indirect
lookup we do in the interpreter core. No biggie. Slower, but no
biggie.
--
Dan

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

Dan Sugalski

unread,
May 15, 2003, 7:48:12 AM5/15/03
to K Stol, perl6-i...@perl.org
At 5:14 PM +0200 5/13/03, K Stol wrote:
>hello,
>
>I've got a very strange idea, and probably it doesn't make sense for
>other people, but maybe someone sees something in it.
>
>The idea is the following. Assume there are some values on the
>runtime stack, let's say "1", "2", "3".
>Now, if they should be restored in a series of registers, say
>registers P5 to P7, it would be nice to do that in a loop,
>so that "1" will be put in P5, "2" in P6, etc.

Ah, register-based indirect indexing. That brings back memories... :)
I can think of two ways to do this.

The first provides actual core support for some of the ops. We could
do it for all the ops, but this'll be so rare as to not be worth
it--I'm not sure that too many compilers will actually emit any code
at all that uses this sort of indexing method. (The nostalgia isn't
enough of a temptation)

The second is to have a fake register PMC that you access by integer
key. Something like:

new .P31, .RegisterFakePMC
set I4, 12
restore P31[I4]

to pop a value off the stack and put it in PMC register 12. Variants
for the int, string, and float registers are doable as well. That
way's really slow, though.

Can you put together a usage case for compiler-generated code, and
the ops that you'll actually do this for? I can see the register
swap, register set, save, and restore ops being used this way, but
not much else. (At least not enough to justify the code and
maintenance)

K Stol

unread,
May 15, 2003, 9:13:30 AM5/15/03
to Dan Sugalski, perl6-i...@perl.org

The case I was thinking of is the following.
(You know I'm working on a Lua compiler to Parrot, right? (and I actually
got something working, too -*yay*))
I'll have to give some background info, because else it won't be clear what
I'm pointing at, I think.
ok, here we go.

Lua has syntax for assignments like these:

a, b, c = 1, 2, 3

This means, all expressions on the RHS are evaluated, and a, b, c get these
values assigned.
Well, when one goes calling functions in these assignments, we'll get this:

a, b, c = f( ), g( ), h( )

(non-last function calls (like f and g) only deliver 1 value, even when the
function itself returns multiple; function calls at the tail deliver all
their values)

Well, first all RHS expr. should be evaluated, so we go calling f:
save all registers, do calling conv. stuff and return values into registers.
But if we now call g, we go save everything, do the usual thing and invoke
the sub.
when we return, the return values are in registers, starting at P5.
When all results of the 3 function calls must be combined, it gets
complicated. Very complicated.

So I decided to do things a bit different. I'm using the stack for returning
values. So now all results are on the
stack. But, if other languages must call Lua functions, the lua functions
should adhere to the parrot call.conv.
So, I'm creating "stubs" for "exported" (=global) functions.
This must be done also for prepending the underscore to the function name.

So, this will result in this stub:

.sub _f
P0 = global "f" -- get current value of "f" (should be a function)
invoke -- the calling function has already put the arguments
in the right registers, so leave them there
-- put return values in registers, where they belong according to Parrot
calling conv.
restore P5 -- function f may be another function than expected,
so there may be no
restore P6 -- values on the stack!
restore P7
ret -- return to calling function (written in other
language)
.end

So, the above will run fine, as long as there *are* values on the stack to
restore. But this may not be the case
so we have to check on that.
We do know the number of return values, that's in I3 (Lua only has
non-prototyped functions, so only PMC ret.vals)
So, it would be nice to do:

.sub _f
...(call function)...
# now go restoring values into registers:
# save nr of ret values in temp:
$P20 = I3
# set index-like var:
x = 5 # we start restoring into register P5
START:
if $P20 == 0, END
restore Px # restore in register, pointed by Px (first time:
P5, 2nd time: P6, etc.)
dec $P20
goto START
END:
ret
.end

I hope I made my point somewhat clearer.
The alternative is to roll out the loop, all in code. This is not nice,
especially when there are 10 return values.
I know, this will not happen *that* often, but it Can Happen.
Also, I'm, of course, talking from my view/interests, but, as Parrot will be
targeted by other languages that may
be as dynamic as Lua, it may be worth thinking about it. (I don't know Perl,
so can't say how things will be handled there)

If things are not clear, I'll be here! :-)

Klaas-Jan

Luke Palmer

unread,
May 15, 2003, 9:49:16 AM5/15/03
to k_s...@hotmail.com, d...@sidhe.org, perl6-i...@perl.org
> > Can you put together a usage case for compiler-generated code, and
> > the ops that you'll actually do this for? I can see the register
> > swap, register set, save, and restore ops being used this way, but
> > not much else. (At least not enough to justify the code and
> > maintenance)
> > --
> The case I was thinking of is the following.
> (You know I'm working on a Lua compiler to Parrot, right? (and I actually
> got something working, too -*yay*))
> I'll have to give some background info, because else it won't be clear what
> I'm pointing at, I think.
> ok, here we go.
>
> Lua has syntax for assignments like these:
>
> a, b, c = 1, 2, 3

Yeah, so does Perl.

> This means, all expressions on the RHS are evaluated, and a, b, c get these
> values assigned.
> Well, when one goes calling functions in these assignments, we'll get this:
>
> a, b, c = f( ), g( ), h( )
>
> (non-last function calls (like f and g) only deliver 1 value, even when the
> function itself returns multiple; function calls at the tail deliver all
> their values)

[...]

> I hope I made my point somewhat clearer.
> The alternative is to roll out the loop, all in code. This is not nice,
> especially when there are 10 return values.
> I know, this will not happen *that* often, but it Can Happen.
> Also, I'm, of course, talking from my view/interests, but, as Parrot will be
> targeted by other languages that may
> be as dynamic as Lua, it may be worth thinking about it. (I don't know Perl,
> so can't say how things will be handled there)

In Perl,

($a, $b, $c) = (f, g, h);

Is list assignment. And it might be implemented that way---build a
list and then iterate over it assigning [binding] each variable. Is
that a possibility for Lua?

I just realized that such a magical PMC (or whatever mechanism does
indirect register assignment) will confuse the heck out of IMCC.

Luke

K Stol

unread,
May 15, 2003, 9:58:12 AM5/15/03
to Luke Palmer, d...@sidhe.org, perl6-i...@perl.org

----- Original Message -----
From: "Luke Palmer" <fibo...@babylonia.flatirons.org>
To: <k_s...@hotmail.com>
Cc: <d...@sidhe.org>; <perl6-i...@perl.org>
Sent: Thursday, May 15, 2003 3:49 PM
Subject: Re: indexing registers or something

You mean, building a list in 1 PMC register? Then, when all results should
be stuffed into the list,
and when traversing the var-list ($a, $b, etc), assigning values from this
list.
like:

P20 = new Array # or something to store stuff
P20[0] = <result expr 1>
P20[1] = <result expr 2>
# etc.
$a = P20[0] # actually, this will be: 'global "a" = P20[0]'
$b = P20[1]
#etc.

something like this?

Klaas-Jan

Dan Sugalski

unread,
May 20, 2003, 4:13:26 PM5/20/03
to K Stol, perl6-i...@perl.org
At 3:13 PM +0200 5/15/03, K Stol wrote:
[As I snip heavily, as I'm rather late here]

>The case I was thinking of is the following.
>(You know I'm working on a Lua compiler to Parrot, right? (and I actually
>got something working, too -*yay*))

Yay indeed!

>I'll have to give some background info, because else it won't be clear what
>I'm pointing at, I think.
>ok, here we go.
>
>Lua has syntax for assignments like these:
>
>a, b, c = 1, 2, 3
>
>This means, all expressions on the RHS are evaluated, and a, b, c get these
>values assigned.
>Well, when one goes calling functions in these assignments, we'll get this:
>
>a, b, c = f( ), g( ), h( )
>
>(non-last function calls (like f and g) only deliver 1 value, even when the
>function itself returns multiple; function calls at the tail deliver all
>their values)

There are two ways to handle this.

The first is that you evaluate the elements of the rhs, and push each
return value onto the user stack. Then you pop the return value into
the elements on the lhs in order. Don't need much in the way of
complexity there, and it ought to work out OK.

The alternative is to build up two lists, one with a, b, and c in it,
the other with the results of the function in it, and assign one to
the other. This may well be what we want to do for parrot in general,
as it's something perl will need to do.

Something like:

new P1, .ListThing
push P1, P2
push P1, P3
push P1, P4
new p10, .ListThing
push P10, P11
push P10, P12
push P10, P13
set P1, P10

if the results are in 11, 12, and 13, and the variables are in 2, 3, and 4.

Alternately, you might want to double-check how Lua handles
assignment, since it's possible that you don't want to do this at
all. If assignment is essentially name-rebinding, the more correct
thing would be:

storeglobal "a", P11
storeglobal "b", P12
storeglobal "c", P13

assuming, once again, the results are in 11, 12, and 13.

Depends on Lua's semantics, of course.

0 new messages